mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-07-13 00:21:25 +08:00
🎨 Style(custom): lint code
This commit is contained in:
@@ -1,57 +1,56 @@
|
|||||||
/// <reference types="vitest/config" />
|
/// <reference types="vitest/config" />
|
||||||
import { dirname, resolve } from 'node:path'
|
import { dirname, resolve } from 'node:path'
|
||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
|
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
|
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
main: {
|
main: {
|
||||||
plugins: [
|
plugins: [externalizeDepsPlugin()],
|
||||||
externalizeDepsPlugin()
|
resolve: {
|
||||||
],
|
alias: {
|
||||||
resolve: {
|
'@': resolve('src/renderer'),
|
||||||
alias: {
|
'~': resolve('src/main'),
|
||||||
'@': resolve('src/renderer'),
|
root: resolve('./'),
|
||||||
'~': resolve('src/main'),
|
'#': resolve('src/universal'),
|
||||||
root: resolve('./'),
|
apis: resolve('src/main/apis'),
|
||||||
'#': resolve('src/universal'),
|
'@core': resolve('src/main/apis/core')
|
||||||
apis: resolve('src/main/apis'),
|
}
|
||||||
'@core': resolve('src/main/apis/core')
|
}
|
||||||
}
|
},
|
||||||
}
|
preload: {
|
||||||
},
|
plugins: [
|
||||||
preload: {
|
externalizeDepsPlugin(),
|
||||||
plugins: [externalizeDepsPlugin(),
|
VueI18nPlugin({
|
||||||
VueI18nPlugin({
|
/* options */
|
||||||
/* options */
|
// locale messages resource pre-compile option
|
||||||
// locale messages resource pre-compile option
|
include: resolve(dirname(fileURLToPath(import.meta.url)), './src/renderer/i18n/locales/**')
|
||||||
include: resolve(dirname(fileURLToPath(import.meta.url)), './src/renderer/i18n/locales/**')
|
})
|
||||||
})
|
],
|
||||||
],
|
resolve: {
|
||||||
resolve: {
|
alias: {
|
||||||
alias: {
|
'@': resolve('src/renderer'),
|
||||||
'@': resolve('src/renderer'),
|
'~': resolve('src/main'),
|
||||||
'~': resolve('src/main'),
|
root: resolve('./'),
|
||||||
root: resolve('./'),
|
'#': resolve('src/universal')
|
||||||
'#': resolve('src/universal')
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
renderer: {
|
||||||
renderer: {
|
root: resolve('src/renderer'),
|
||||||
root: resolve('src/renderer'),
|
base: './',
|
||||||
base: './',
|
resolve: {
|
||||||
resolve: {
|
alias: {
|
||||||
alias: {
|
'@': resolve('src/renderer'),
|
||||||
'@': resolve('src/renderer'),
|
'~': resolve('src/main'),
|
||||||
'~': resolve('src/main'),
|
root: resolve('./'),
|
||||||
root: resolve('./'),
|
'#': resolve('src/universal')
|
||||||
'#': resolve('src/universal')
|
}
|
||||||
}
|
},
|
||||||
},
|
plugins: [vue()],
|
||||||
plugins: [vue()],
|
server: {
|
||||||
server: {
|
port: 3000
|
||||||
port: 3000
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import eslint from '@eslint/js'
|
import eslint from '@eslint/js'
|
||||||
import standard from '@vue/eslint-config-standard'
|
import standard from '@vue/eslint-config-standard'
|
||||||
|
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
|
||||||
import simpleImportSort from 'eslint-plugin-simple-import-sort'
|
import simpleImportSort from 'eslint-plugin-simple-import-sort'
|
||||||
import eslintPluginUnicorn from 'eslint-plugin-unicorn'
|
import eslintPluginUnicorn from 'eslint-plugin-unicorn'
|
||||||
import pluginVue from 'eslint-plugin-vue'
|
import pluginVue from 'eslint-plugin-vue'
|
||||||
@@ -18,6 +19,7 @@ export default tseslint.config(
|
|||||||
...tseslint.configs.stylistic,
|
...tseslint.configs.stylistic,
|
||||||
...pluginVue.configs['flat/recommended'],
|
...pluginVue.configs['flat/recommended'],
|
||||||
...standard,
|
...standard,
|
||||||
|
eslintPluginPrettierRecommended,
|
||||||
{
|
{
|
||||||
plugins: {
|
plugins: {
|
||||||
'simple-import-sort': simpleImportSort,
|
'simple-import-sort': simpleImportSort,
|
||||||
|
|||||||
15
package.json
15
package.json
@@ -25,10 +25,10 @@
|
|||||||
"dev": "electron-vite dev --watch",
|
"dev": "electron-vite dev --watch",
|
||||||
"i18n": "node ./scripts/gen-i18n-types.js",
|
"i18n": "node ./scripts/gen-i18n-types.js",
|
||||||
"link": "node ./scripts/link.js",
|
"link": "node ./scripts/link.js",
|
||||||
"lint": "eslint --ext .js,.jsx,.ts,.tsx,.vue src/",
|
"lint": "eslint --ext .js,.jsx,.ts,.tsx,.vue src/ scripts/ .",
|
||||||
"lint:dpdm": "dpdm -T --tsconfig ./tsconfig.json --no-tree --no-warning --exit-code circular:1 src/main/index.ts",
|
"lint:dpdm": "dpdm -T --tsconfig ./tsconfig.json --no-tree --no-warning --exit-code circular:1 src/main/index.ts",
|
||||||
"lint:dpdm:renderer": "dpdm -T --tsconfig ./tsconfig.json --no-tree --no-warning --exit-code circular:1 src/renderer/main.ts",
|
"lint:dpdm:renderer": "dpdm -T --tsconfig ./tsconfig.json --no-tree --no-warning --exit-code circular:1 src/renderer/main.ts",
|
||||||
"lint:fix": "eslint --fix --ext .js,.jsx,.ts,.tsx,.vue src/",
|
"lint:fix": "eslint --fix --ext .js,.jsx,.ts,.tsx,.vue src/ scripts/ .",
|
||||||
"ncu": "node ./scripts/check-dep.js",
|
"ncu": "node ./scripts/check-dep.js",
|
||||||
"postinstall": "electron-builder install-app-deps",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"postuninstall": "electron-builder install-app-deps",
|
"postuninstall": "electron-builder install-app-deps",
|
||||||
@@ -44,7 +44,6 @@
|
|||||||
"@aws-sdk/client-s3": "^3.864.0",
|
"@aws-sdk/client-s3": "^3.864.0",
|
||||||
"@aws-sdk/lib-storage": "^3.864.0",
|
"@aws-sdk/lib-storage": "^3.864.0",
|
||||||
"@aws-sdk/s3-request-presigner": "^3.864.0",
|
"@aws-sdk/s3-request-presigner": "^3.864.0",
|
||||||
"@electron-toolkit/preload": "^3.0.2",
|
|
||||||
"@headlessui/vue": "^1.7.23",
|
"@headlessui/vue": "^1.7.23",
|
||||||
"@highlightjs/vue-plugin": "^2.1.2",
|
"@highlightjs/vue-plugin": "^2.1.2",
|
||||||
"@nodelib/fs.walk": "^3.0.1",
|
"@nodelib/fs.walk": "^3.0.1",
|
||||||
@@ -53,11 +52,12 @@
|
|||||||
"@piclist/store": "^3.0.0",
|
"@piclist/store": "^3.0.0",
|
||||||
"@smithy/node-http-handler": "^4.1.1",
|
"@smithy/node-http-handler": "^4.1.1",
|
||||||
"@videojs-player/vue": "^1.0.0",
|
"@videojs-player/vue": "^1.0.0",
|
||||||
"@vueuse/core": "^13.6.0",
|
|
||||||
"ali-oss": "^6.23.0",
|
"ali-oss": "^6.23.0",
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.11.0",
|
||||||
|
"chalk": "^5.5.0",
|
||||||
"compare-versions": "^6.1.1",
|
"compare-versions": "^6.1.1",
|
||||||
"cos-nodejs-sdk-v5": "^2.15.4",
|
"cos-nodejs-sdk-v5": "^2.15.4",
|
||||||
|
"dayjs": "^1.11.13",
|
||||||
"dexie": "^3.2.4",
|
"dexie": "^3.2.4",
|
||||||
"electron-updater": "^6.6.2",
|
"electron-updater": "^6.6.2",
|
||||||
"fast-xml-parser": "^5.2.5",
|
"fast-xml-parser": "^5.2.5",
|
||||||
@@ -78,13 +78,12 @@
|
|||||||
"piclist": "^2.0.0",
|
"piclist": "^2.0.0",
|
||||||
"pinia": "^3.0.3",
|
"pinia": "^3.0.3",
|
||||||
"pinia-plugin-persistedstate": "^4.5.0",
|
"pinia-plugin-persistedstate": "^4.5.0",
|
||||||
"proxy-agent": "^6.5.0",
|
|
||||||
"qiniu": "7.14.0",
|
"qiniu": "7.14.0",
|
||||||
"qrcode.vue": "^3.6.0",
|
"qrcode.vue": "^3.6.0",
|
||||||
"querystring": "^0.2.1",
|
|
||||||
"semver": "^7.7.2",
|
"semver": "^7.7.2",
|
||||||
"shell-path": "3.0.0",
|
"shell-path": "3.0.0",
|
||||||
"ssh2-no-cpu-features": "^2.0.0",
|
"ssh2-no-cpu-features": "^2.0.0",
|
||||||
|
"tunnel": "^0.0.6",
|
||||||
"upyun": "^3.4.6",
|
"upyun": "^3.4.6",
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
"video.js": "^8.23.4",
|
"video.js": "^8.23.4",
|
||||||
@@ -112,9 +111,7 @@
|
|||||||
"@types/video.js": "^7.3.58",
|
"@types/video.js": "^7.3.58",
|
||||||
"@types/write-file-atomic": "^4.0.3",
|
"@types/write-file-atomic": "^4.0.3",
|
||||||
"@vitejs/plugin-vue": "^6.0.1",
|
"@vitejs/plugin-vue": "^6.0.1",
|
||||||
"@vue/eslint-config-prettier": "^10.2.0",
|
|
||||||
"@vue/eslint-config-standard": "^9.0.1",
|
"@vue/eslint-config-standard": "^9.0.1",
|
||||||
"@vue/eslint-config-typescript": "^14.6.0",
|
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"dpdm": "^3.14.0",
|
"dpdm": "^3.14.0",
|
||||||
"electron": "^36.7.4",
|
"electron": "^36.7.4",
|
||||||
@@ -122,10 +119,12 @@
|
|||||||
"electron-devtools-installer": "^4.0.0",
|
"electron-devtools-installer": "^4.0.0",
|
||||||
"electron-vite": "^4.0.0",
|
"electron-vite": "^4.0.0",
|
||||||
"eslint": "^9.33.0",
|
"eslint": "^9.33.0",
|
||||||
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-prettier": "^5.5.4",
|
"eslint-plugin-prettier": "^5.5.4",
|
||||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||||
"eslint-plugin-unicorn": "^60.0.0",
|
"eslint-plugin-unicorn": "^60.0.0",
|
||||||
"eslint-plugin-vue": "^10.4.0",
|
"eslint-plugin-vue": "^10.4.0",
|
||||||
|
"globals": "^16.3.0",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"node-bump-version": "^2.0.0",
|
"node-bump-version": "^2.0.0",
|
||||||
"npm-check-updates": "^18.0.2",
|
"npm-check-updates": "^18.0.2",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { run } from 'npm-check-updates'
|
import { run } from 'npm-check-updates'
|
||||||
|
|
||||||
async function getRepositoryInfo (packageName) {
|
async function getRepositoryInfo(packageName) {
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.get(`https://registry.npmjs.org/${packageName}`)
|
const { data } = await axios.get(`https://registry.npmjs.org/${packageName}`)
|
||||||
const repository = data.repository
|
const repository = data.repository
|
||||||
@@ -17,7 +17,7 @@ async function getRepositoryInfo (packageName) {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkUpdates () {
|
async function checkUpdates() {
|
||||||
const updated = await run({
|
const updated = await run({
|
||||||
packageFile: './package.json',
|
packageFile: './package.json',
|
||||||
upgrade: false
|
upgrade: false
|
||||||
|
|||||||
@@ -1,66 +1,66 @@
|
|||||||
// different platform has different format
|
// different platform has different format
|
||||||
|
|
||||||
// macos
|
// macos
|
||||||
const darwin = [
|
const darwin = [
|
||||||
{
|
{
|
||||||
appNameWithPrefix: 'PicList-',
|
appNameWithPrefix: 'PicList-',
|
||||||
ext: '.dmg',
|
ext: '.dmg',
|
||||||
arch: '-arm64',
|
arch: '-arm64',
|
||||||
'version-file': 'latest-mac.yml'
|
'version-file': 'latest-mac.yml'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
appNameWithPrefix: 'PicList-',
|
appNameWithPrefix: 'PicList-',
|
||||||
ext: '.dmg',
|
ext: '.dmg',
|
||||||
arch: '-x64',
|
arch: '-x64',
|
||||||
'version-file': 'latest-mac.yml'
|
'version-file': 'latest-mac.yml'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const linux = [
|
const linux = [
|
||||||
{
|
{
|
||||||
appNameWithPrefix: 'PicList-',
|
appNameWithPrefix: 'PicList-',
|
||||||
ext: '.AppImage',
|
ext: '.AppImage',
|
||||||
arch: '',
|
arch: '',
|
||||||
'version-file': 'latest-linux.yml'
|
'version-file': 'latest-linux.yml'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
appNameWithPrefix: 'piclist_',
|
appNameWithPrefix: 'piclist_',
|
||||||
ext: '.snap',
|
ext: '.snap',
|
||||||
arch: '_amd64',
|
arch: '_amd64',
|
||||||
'version-file': 'latest-linux.yml'
|
'version-file': 'latest-linux.yml'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
// windows
|
// windows
|
||||||
const win32 = [
|
const win32 = [
|
||||||
{
|
{
|
||||||
appNameWithPrefix: 'PicList-Setup-',
|
appNameWithPrefix: 'PicList-Setup-',
|
||||||
ext: '.exe',
|
ext: '.exe',
|
||||||
arch: '-ia32',
|
arch: '-ia32',
|
||||||
'version-file': 'latest.yml'
|
'version-file': 'latest.yml'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
appNameWithPrefix: 'PicList-Setup-',
|
appNameWithPrefix: 'PicList-Setup-',
|
||||||
ext: '.exe',
|
ext: '.exe',
|
||||||
arch: '-x64',
|
arch: '-x64',
|
||||||
'version-file': 'latest.yml'
|
'version-file': 'latest.yml'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
appNameWithPrefix: 'PicList-Setup-',
|
appNameWithPrefix: 'PicList-Setup-',
|
||||||
ext: '.exe',
|
ext: '.exe',
|
||||||
arch: '', // 32 & 64
|
arch: '', // 32 & 64
|
||||||
'version-file': 'latest.yml'
|
'version-file': 'latest.yml'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
appNameWithPrefix: 'PicList-Setup-',
|
appNameWithPrefix: 'PicList-Setup-',
|
||||||
ext: '.exe',
|
ext: '.exe',
|
||||||
arch: '-arm64',
|
arch: '-arm64',
|
||||||
'version-file': 'latest.yml'
|
'version-file': 'latest.yml'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
darwin,
|
darwin,
|
||||||
linux,
|
linux,
|
||||||
win32
|
win32
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import path from 'node:path'
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
|
||||||
import pkg from '../package.json' with { type: 'json'}
|
import pkg from '../package.json' with { type: 'json' }
|
||||||
const version = process.argv[2] || pkg.version
|
const version = process.argv[2] || pkg.version
|
||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
@@ -26,7 +26,7 @@ const files = [
|
|||||||
/**
|
/**
|
||||||
* Create progress bar string
|
* Create progress bar string
|
||||||
*/
|
*/
|
||||||
function getProgressBar (current, total, length = 20) {
|
function getProgressBar(current, total, length = 20) {
|
||||||
const progress = Math.round((current / total) * length)
|
const progress = Math.round((current / total) * length)
|
||||||
const percentage = Math.round((current / total) * 100)
|
const percentage = Math.round((current / total) * 100)
|
||||||
const bar = '█'.repeat(progress) + '░'.repeat(length - progress)
|
const bar = '█'.repeat(progress) + '░'.repeat(length - progress)
|
||||||
@@ -36,7 +36,7 @@ function getProgressBar (current, total, length = 20) {
|
|||||||
/**
|
/**
|
||||||
* Format bytes to human-readable format
|
* Format bytes to human-readable format
|
||||||
*/
|
*/
|
||||||
function formatBytes (bytes, decimals = 2) {
|
function formatBytes(bytes, decimals = 2) {
|
||||||
if (bytes === 0) return '0 Bytes'
|
if (bytes === 0) return '0 Bytes'
|
||||||
const k = 1024
|
const k = 1024
|
||||||
const sizes = ['Bytes', 'KB', 'MB', 'GB']
|
const sizes = ['Bytes', 'KB', 'MB', 'GB']
|
||||||
@@ -47,7 +47,7 @@ function formatBytes (bytes, decimals = 2) {
|
|||||||
/**
|
/**
|
||||||
* Download file and calculate SHA256 hash
|
* Download file and calculate SHA256 hash
|
||||||
*/
|
*/
|
||||||
async function downloadAndHash (fileInfo) {
|
async function downloadAndHash(fileInfo) {
|
||||||
const { url, name } = fileInfo
|
const { url, name } = fileInfo
|
||||||
const filePath = path.join(DOWNLOAD_DIR, name)
|
const filePath = path.join(DOWNLOAD_DIR, name)
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ async function downloadAndHash (fileInfo) {
|
|||||||
/**
|
/**
|
||||||
* Main function
|
* Main function
|
||||||
*/
|
*/
|
||||||
async function main () {
|
async function main() {
|
||||||
console.log(`Generating SHA256 hashes for PicList v${version}`)
|
console.log(`Generating SHA256 hashes for PicList v${version}`)
|
||||||
console.log(`Download directory: ${DOWNLOAD_DIR}`)
|
console.log(`Download directory: ${DOWNLOAD_DIR}`)
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
import pkg from '../package.json' with { type: 'json' }
|
import pkg from '../package.json' with { type: 'json' }
|
||||||
const version = pkg.version
|
const version = pkg.version
|
||||||
// TODO: use the same name format
|
// TODO: use the same name format
|
||||||
const generateURL = (platform, ext, prefix = 'PicList-') => {
|
const generateURL = (platform, ext, prefix = 'PicList-') => {
|
||||||
return `https://release.piclist.cn/latest/${prefix}${version}${platform}${ext}`
|
return `https://release.piclist.cn/latest/${prefix}${version}${platform}${ext}`
|
||||||
}
|
}
|
||||||
|
|
||||||
const template = `
|
const template = `
|
||||||
### 加速下载地址
|
### 加速下载地址
|
||||||
|
|
||||||
#### MacOS
|
#### MacOS
|
||||||
[PicList-${version}-arm64.dmg](${generateURL('-arm64', '.dmg', 'PicList-')})
|
[PicList-${version}-arm64.dmg](${generateURL('-arm64', '.dmg', 'PicList-')})
|
||||||
[PicList-${version}-x64.dmg](${generateURL('-x64', '.dmg', 'PicList-')})
|
[PicList-${version}-x64.dmg](${generateURL('-x64', '.dmg', 'PicList-')})
|
||||||
[PicList-${version}-universal.dmg](${generateURL('-universal', '.dmg', 'PicList-')})
|
[PicList-${version}-universal.dmg](${generateURL('-universal', '.dmg', 'PicList-')})
|
||||||
|
|
||||||
#### Windows
|
#### Windows
|
||||||
[PicList-Setup-${version}-ia32.exe](${generateURL('-ia32', '.exe', 'PicList-Setup-')})
|
[PicList-Setup-${version}-ia32.exe](${generateURL('-ia32', '.exe', 'PicList-Setup-')})
|
||||||
[PicList-Setup-${version}-x64.exe](${generateURL('-x64', '.exe', 'PicList-Setup-')})
|
[PicList-Setup-${version}-x64.exe](${generateURL('-x64', '.exe', 'PicList-Setup-')})
|
||||||
[PicList-Setup-${version}-arm64.exe](${generateURL('-arm64', '.exe', 'PicList-Setup-')})
|
[PicList-Setup-${version}-arm64.exe](${generateURL('-arm64', '.exe', 'PicList-Setup-')})
|
||||||
[PicList-Setup-${version}.exe](${generateURL('', '.exe', 'PicList-Setup-')})
|
[PicList-Setup-${version}.exe](${generateURL('', '.exe', 'PicList-Setup-')})
|
||||||
|
|
||||||
#### Linux
|
#### Linux
|
||||||
[PicList-${version}.AppImage](${generateURL('', '.AppImage', 'PicList-')})
|
[PicList-${version}.AppImage](${generateURL('', '.AppImage', 'PicList-')})
|
||||||
[piclist_${version}_amd64.snap](${generateURL('_amd64', '.snap', 'piclist_')})`
|
[piclist_${version}_amd64.snap](${generateURL('_amd64', '.snap', 'piclist_')})`
|
||||||
|
|
||||||
console.log(template)
|
console.log(template)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ require('dotenv').config()
|
|||||||
const { notarize } = require('@electron/notarize')
|
const { notarize } = require('@electron/notarize')
|
||||||
const { ELECTRON_SKIP_NOTARIZATION, XCODE_APP_LOADER_EMAIL, XCODE_APP_LOADER_PASSWORD, XCODE_TEAM_ID } = process.env
|
const { ELECTRON_SKIP_NOTARIZATION, XCODE_APP_LOADER_EMAIL, XCODE_APP_LOADER_PASSWORD, XCODE_TEAM_ID } = process.env
|
||||||
|
|
||||||
async function main (context) {
|
async function main(context) {
|
||||||
const { electronPlatformName, appOutDir } = context
|
const { electronPlatformName, appOutDir } = context
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ class RemoteNoticeHandler {
|
|||||||
private remoteNotice: IRemoteNotice | null = null
|
private remoteNotice: IRemoteNotice | null = null
|
||||||
private remoteNoticeLocalCountStorage: IRemoteNoticeLocalCountStorage | null = null
|
private remoteNoticeLocalCountStorage: IRemoteNoticeLocalCountStorage | null = null
|
||||||
|
|
||||||
async init () {
|
async init() {
|
||||||
this.remoteNotice = await this.getRemoteNoticeInfo()
|
this.remoteNotice = await this.getRemoteNoticeInfo()
|
||||||
this.initLocalCountStorage()
|
this.initLocalCountStorage()
|
||||||
}
|
}
|
||||||
|
|
||||||
private initLocalCountStorage () {
|
private initLocalCountStorage() {
|
||||||
const localCountStorage = {}
|
const localCountStorage = {}
|
||||||
if (!fs.existsSync(REMOTE_NOTICE_LOCAL_STORAGE_PATH)) {
|
if (!fs.existsSync(REMOTE_NOTICE_LOCAL_STORAGE_PATH)) {
|
||||||
fs.writeFileSync(REMOTE_NOTICE_LOCAL_STORAGE_PATH, JSON.stringify({}))
|
fs.writeFileSync(REMOTE_NOTICE_LOCAL_STORAGE_PATH, JSON.stringify({}))
|
||||||
@@ -44,14 +44,14 @@ class RemoteNoticeHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private saveLocalCountStorage (newData?: IRemoteNoticeLocalCountStorage) {
|
private saveLocalCountStorage(newData?: IRemoteNoticeLocalCountStorage) {
|
||||||
if (newData) {
|
if (newData) {
|
||||||
this.remoteNoticeLocalCountStorage = newData
|
this.remoteNoticeLocalCountStorage = newData
|
||||||
}
|
}
|
||||||
fs.writeFileSync(REMOTE_NOTICE_LOCAL_STORAGE_PATH, JSON.stringify(this.remoteNoticeLocalCountStorage))
|
fs.writeFileSync(REMOTE_NOTICE_LOCAL_STORAGE_PATH, JSON.stringify(this.remoteNoticeLocalCountStorage))
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getRemoteNoticeInfo (): Promise<IRemoteNotice | null> {
|
private async getRemoteNoticeInfo(): Promise<IRemoteNotice | null> {
|
||||||
try {
|
try {
|
||||||
const noticeInfo = (await axios({
|
const noticeInfo = (await axios({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
@@ -68,7 +68,7 @@ class RemoteNoticeHandler {
|
|||||||
* if the notice is not shown or is always shown, then show the notice
|
* if the notice is not shown or is always shown, then show the notice
|
||||||
* @param action
|
* @param action
|
||||||
*/
|
*/
|
||||||
private checkActionCount (action: IRemoteNoticeAction) {
|
private checkActionCount(action: IRemoteNoticeAction) {
|
||||||
try {
|
try {
|
||||||
if (!this.remoteNoticeLocalCountStorage) {
|
if (!this.remoteNoticeLocalCountStorage) {
|
||||||
return true
|
return true
|
||||||
@@ -102,7 +102,7 @@ class RemoteNoticeHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async doActions (actions: IRemoteNoticeAction[]) {
|
private async doActions(actions: IRemoteNoticeAction[]) {
|
||||||
for (const action of actions) {
|
for (const action of actions) {
|
||||||
if (this.checkActionCount(action)) {
|
if (this.checkActionCount(action)) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
@@ -117,7 +117,7 @@ class RemoteNoticeHandler {
|
|||||||
body: action.data?.content || '',
|
body: action.data?.content || '',
|
||||||
clickToCopy: !!action.data?.copyToClipboard,
|
clickToCopy: !!action.data?.copyToClipboard,
|
||||||
copyContent: action.data?.copyToClipboard || '',
|
copyContent: action.data?.copyToClipboard || '',
|
||||||
clickFn () {
|
clickFn() {
|
||||||
if (action.data?.url) {
|
if (action.data?.url) {
|
||||||
shell.openExternal(action.data.url)
|
shell.openExternal(action.data.url)
|
||||||
}
|
}
|
||||||
@@ -163,7 +163,7 @@ class RemoteNoticeHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
triggerHook (hook: string) {
|
triggerHook(hook: string) {
|
||||||
if (!this.remoteNotice || !this.remoteNotice.list) {
|
if (!this.remoteNotice || !this.remoteNotice.list) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,24 +6,30 @@ import shortKeyService from 'apis/app/shortKey/shortKeyService'
|
|||||||
import GuiApi from 'apis/gui'
|
import GuiApi from 'apis/gui'
|
||||||
import { globalShortcut } from 'electron'
|
import { globalShortcut } from 'electron'
|
||||||
|
|
||||||
import type { IKeyCommandType, IPluginShortKeyConfig, IShortKeyConfig, IShortKeyConfigs, IShortKeyHandler } from '#/types/types'
|
import type {
|
||||||
|
IKeyCommandType,
|
||||||
|
IPluginShortKeyConfig,
|
||||||
|
IShortKeyConfig,
|
||||||
|
IShortKeyConfigs,
|
||||||
|
IShortKeyHandler
|
||||||
|
} from '#/types/types'
|
||||||
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '~/events/constant'
|
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '~/events/constant'
|
||||||
import { configPaths } from '~/utils/configPaths'
|
import { configPaths } from '~/utils/configPaths'
|
||||||
|
|
||||||
class ShortKeyHandler {
|
class ShortKeyHandler {
|
||||||
private isInModifiedMode: boolean = false
|
private isInModifiedMode: boolean = false
|
||||||
constructor () {
|
constructor() {
|
||||||
bus.on(TOGGLE_SHORTKEY_MODIFIED_MODE, flag => {
|
bus.on(TOGGLE_SHORTKEY_MODIFIED_MODE, flag => {
|
||||||
this.isInModifiedMode = flag
|
this.isInModifiedMode = flag
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async init () {
|
async init() {
|
||||||
this.initBuiltInShortKey()
|
this.initBuiltInShortKey()
|
||||||
await this.initPluginsShortKey()
|
await this.initPluginsShortKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
private initBuiltInShortKey () {
|
private initBuiltInShortKey() {
|
||||||
const commands = db.get(configPaths.settings.shortKey._path) as IShortKeyConfigs
|
const commands = db.get(configPaths.settings.shortKey._path) as IShortKeyConfigs
|
||||||
Object.keys(commands)
|
Object.keys(commands)
|
||||||
.filter(item => item.includes('picgo:'))
|
.filter(item => item.includes('picgo:'))
|
||||||
@@ -38,7 +44,7 @@ class ShortKeyHandler {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private async initPluginsShortKey () {
|
private async initPluginsShortKey() {
|
||||||
// get enabled plugin
|
// get enabled plugin
|
||||||
const pluginList = picgo.pluginLoader.getList()
|
const pluginList = picgo.pluginLoader.getList()
|
||||||
for (const item of pluginList) {
|
for (const item of pluginList) {
|
||||||
@@ -68,7 +74,7 @@ class ShortKeyHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerShortKey (
|
private registerShortKey(
|
||||||
config: IShortKeyConfig | IPluginShortKeyConfig,
|
config: IShortKeyConfig | IPluginShortKeyConfig,
|
||||||
command: string,
|
command: string,
|
||||||
handler: IShortKeyHandler,
|
handler: IShortKeyHandler,
|
||||||
@@ -97,7 +103,7 @@ class ShortKeyHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// enable or disable shortKey
|
// enable or disable shortKey
|
||||||
bindOrUnbindShortKey (item: IShortKeyConfig, from: string): boolean {
|
bindOrUnbindShortKey(item: IShortKeyConfig, from: string): boolean {
|
||||||
const command = `${from}:${item.name}`
|
const command = `${from}:${item.name}`
|
||||||
if (item.enable === false) {
|
if (item.enable === false) {
|
||||||
globalShortcut.unregister(item.key)
|
globalShortcut.unregister(item.key)
|
||||||
@@ -121,7 +127,7 @@ class ShortKeyHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update shortKey bindings
|
// update shortKey bindings
|
||||||
updateShortKey (item: IShortKeyConfig, oldKey: string, from: string): boolean {
|
updateShortKey(item: IShortKeyConfig, oldKey: string, from: string): boolean {
|
||||||
const command = `${from}:${item.name}`
|
const command = `${from}:${item.name}`
|
||||||
if (globalShortcut.isRegistered(item.key)) return false
|
if (globalShortcut.isRegistered(item.key)) return false
|
||||||
globalShortcut.unregister(oldKey)
|
globalShortcut.unregister(oldKey)
|
||||||
@@ -134,7 +140,7 @@ class ShortKeyHandler {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handler (command: string) {
|
private async handler(command: string) {
|
||||||
if (this.isInModifiedMode) {
|
if (this.isInModifiedMode) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -150,7 +156,7 @@ class ShortKeyHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async registerPluginShortKey (pluginName: string) {
|
async registerPluginShortKey(pluginName: string) {
|
||||||
const plugin = await picgo.pluginLoader.getPlugin(pluginName)
|
const plugin = await picgo.pluginLoader.getPlugin(pluginName)
|
||||||
if (plugin && plugin.commands) {
|
if (plugin && plugin.commands) {
|
||||||
if (typeof plugin.commands !== 'function') {
|
if (typeof plugin.commands !== 'function') {
|
||||||
@@ -170,7 +176,7 @@ class ShortKeyHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unregisterPluginShortKey (pluginName: string) {
|
unregisterPluginShortKey(pluginName: string) {
|
||||||
const commands = db.get(configPaths.settings.shortKey._path) as IShortKeyConfigs
|
const commands = db.get(configPaths.settings.shortKey._path) as IShortKeyConfigs
|
||||||
const keyList = Object.keys(commands)
|
const keyList = Object.keys(commands)
|
||||||
.filter(command => command.includes(pluginName))
|
.filter(command => command.includes(pluginName))
|
||||||
|
|||||||
@@ -4,22 +4,22 @@ import type { IShortKeyHandler } from '#/types/types'
|
|||||||
|
|
||||||
class ShortKeyService {
|
class ShortKeyService {
|
||||||
private commandList: Map<string, IShortKeyHandler> = new Map()
|
private commandList: Map<string, IShortKeyHandler> = new Map()
|
||||||
registerCommand (command: string, handler: IShortKeyHandler) {
|
registerCommand(command: string, handler: IShortKeyHandler) {
|
||||||
this.commandList.set(command, handler)
|
this.commandList.set(command, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
unregisterCommand (command: string) {
|
unregisterCommand(command: string) {
|
||||||
this.commandList.delete(command)
|
this.commandList.delete(command)
|
||||||
}
|
}
|
||||||
|
|
||||||
getShortKeyHandler (command: string): IShortKeyHandler | null {
|
getShortKeyHandler(command: string): IShortKeyHandler | null {
|
||||||
const handler = this.commandList.get(command)
|
const handler = this.commandList.get(command)
|
||||||
if (handler) return handler
|
if (handler) return handler
|
||||||
logger.warn(`cannot find command: ${command}`)
|
logger.warn(`cannot find command: ${command}`)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
getCommandList () {
|
getCommandList() {
|
||||||
return [...this.commandList.keys()]
|
return [...this.commandList.keys()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import uploadPng from '../../../../../resources/upload.png?asset&asarUnpack'
|
|||||||
import uploadDarkPng from '../../../../../resources/upload-dark.png?asset&asarUnpack'
|
import uploadDarkPng from '../../../../../resources/upload-dark.png?asset&asarUnpack'
|
||||||
let contextMenu: Menu | null
|
let contextMenu: Menu | null
|
||||||
|
|
||||||
export function setDockMenu () {
|
export function setDockMenu() {
|
||||||
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
||||||
const dockMenu = Menu.buildFromTemplate([
|
const dockMenu = Menu.buildFromTemplate([
|
||||||
{
|
{
|
||||||
@@ -45,7 +45,7 @@ export function setDockMenu () {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('START_WATCH_CLIPBOARD'),
|
label: $t('START_WATCH_CLIPBOARD'),
|
||||||
click () {
|
click() {
|
||||||
db.set(configPaths.settings.isListeningClipboard, true)
|
db.set(configPaths.settings.isListeningClipboard, true)
|
||||||
clipboardPoll.startListening()
|
clipboardPoll.startListening()
|
||||||
clipboardPoll.on('change', () => {
|
clipboardPoll.on('change', () => {
|
||||||
@@ -58,7 +58,7 @@ export function setDockMenu () {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('STOP_WATCH_CLIPBOARD'),
|
label: $t('STOP_WATCH_CLIPBOARD'),
|
||||||
click () {
|
click() {
|
||||||
db.set(configPaths.settings.isListeningClipboard, false)
|
db.set(configPaths.settings.isListeningClipboard, false)
|
||||||
clipboardPoll.stopListening()
|
clipboardPoll.stopListening()
|
||||||
clipboardPoll.removeAllListeners()
|
clipboardPoll.removeAllListeners()
|
||||||
@@ -70,7 +70,7 @@ export function setDockMenu () {
|
|||||||
app.dock?.setMenu(dockMenu)
|
app.dock?.setMenu(dockMenu)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createMenu () {
|
export function createMenu() {
|
||||||
const submenu = buildPicBedListMenu()
|
const submenu = buildPicBedListMenu()
|
||||||
const appMenu = Menu.buildFromTemplate([
|
const appMenu = Menu.buildFromTemplate([
|
||||||
{
|
{
|
||||||
@@ -79,7 +79,7 @@ export function createMenu () {
|
|||||||
{ label: $t('OPEN_MAIN_WINDOW'), click: openMainWindow },
|
{ label: $t('OPEN_MAIN_WINDOW'), click: openMainWindow },
|
||||||
{
|
{
|
||||||
label: $t('RELOAD_APP'),
|
label: $t('RELOAD_APP'),
|
||||||
click () {
|
click() {
|
||||||
app.relaunch()
|
app.relaunch()
|
||||||
app.exit(0)
|
app.exit(0)
|
||||||
}
|
}
|
||||||
@@ -107,7 +107,7 @@ export function createMenu () {
|
|||||||
Menu.setApplicationMenu(appMenu)
|
Menu.setApplicationMenu(appMenu)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createContextMenu () {
|
export function createContextMenu() {
|
||||||
const ClipboardWatcher = clipboardPoll
|
const ClipboardWatcher = clipboardPoll
|
||||||
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
const isListeningClipboard = db.get(configPaths.settings.isListeningClipboard) || false
|
||||||
const isMiniWindowVisible =
|
const isMiniWindowVisible =
|
||||||
@@ -147,7 +147,7 @@ export function createContextMenu () {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('RELOAD_APP'),
|
label: $t('RELOAD_APP'),
|
||||||
click () {
|
click() {
|
||||||
app.relaunch()
|
app.relaunch()
|
||||||
app.exit(0)
|
app.exit(0)
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ export function createContextMenu () {
|
|||||||
0,
|
0,
|
||||||
{
|
{
|
||||||
label: $t('OPEN_MINI_WINDOW'),
|
label: $t('OPEN_MINI_WINDOW'),
|
||||||
click () {
|
click() {
|
||||||
openMiniWindow(false)
|
openMiniWindow(false)
|
||||||
},
|
},
|
||||||
visible: !isMiniWindowVisible
|
visible: !isMiniWindowVisible
|
||||||
@@ -185,7 +185,7 @@ export function createContextMenu () {
|
|||||||
{ label: $t('OPEN_MAIN_WINDOW'), click: openMainWindow },
|
{ label: $t('OPEN_MAIN_WINDOW'), click: openMainWindow },
|
||||||
{
|
{
|
||||||
label: $t('OPEN_MINI_WINDOW'),
|
label: $t('OPEN_MINI_WINDOW'),
|
||||||
click () {
|
click() {
|
||||||
openMiniWindow(false)
|
openMiniWindow(false)
|
||||||
},
|
},
|
||||||
visible: !isMiniWindowVisible
|
visible: !isMiniWindowVisible
|
||||||
@@ -207,7 +207,7 @@ export function createContextMenu () {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('ABOUT'),
|
label: $t('ABOUT'),
|
||||||
click () {
|
click() {
|
||||||
dialog.showMessageBox({
|
dialog.showMessageBox({
|
||||||
title: 'PicList',
|
title: 'PicList',
|
||||||
message: 'PicList',
|
message: 'PicList',
|
||||||
@@ -230,7 +230,7 @@ const getTrayIcon = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTray (tooltip: string) {
|
export function createTray(tooltip: string) {
|
||||||
const menubarPic = getTrayIcon()
|
const menubarPic = getTrayIcon()
|
||||||
setTray(new Tray(menubarPic))
|
setTray(new Tray(menubarPic))
|
||||||
tray.setToolTip(tooltip)
|
tray.setToolTip(tooltip)
|
||||||
@@ -309,7 +309,7 @@ export function createTray (tooltip: string) {
|
|||||||
// drop-files only be supported in macOS
|
// drop-files only be supported in macOS
|
||||||
// so the tray window must be available
|
// so the tray window must be available
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
(tray as any).on('drop-files', async (_: Event, files: string[]) => {
|
;(tray as any).on('drop-files', async (_: Event, files: string[]) => {
|
||||||
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||||
const rawInput = cloneDeep(files)
|
const rawInput = cloneDeep(files)
|
||||||
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)!
|
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)!
|
||||||
@@ -338,14 +338,14 @@ export function createTray (tooltip: string) {
|
|||||||
imgs[i].shortUrl = shortUrl
|
imgs[i].shortUrl = shortUrl
|
||||||
pasteText.push(pasteTextItem)
|
pasteText.push(pasteTextItem)
|
||||||
const isShowResultNotification =
|
const isShowResultNotification =
|
||||||
db.get(configPaths.settings.uploadResultNotification) === undefined
|
db.get(configPaths.settings.uploadResultNotification) === undefined
|
||||||
? true
|
? true
|
||||||
: !!db.get(configPaths.settings.uploadResultNotification)
|
: !!db.get(configPaths.settings.uploadResultNotification)
|
||||||
if (isShowResultNotification) {
|
if (isShowResultNotification) {
|
||||||
const notification = new Notification({
|
const notification = new Notification({
|
||||||
title: $t('UPLOAD_SUCCEED'),
|
title: $t('UPLOAD_SUCCEED'),
|
||||||
body: shortUrl || imgs[i].imgUrl!
|
body: shortUrl || imgs[i].imgUrl!
|
||||||
// icon: files[i]
|
// icon: files[i]
|
||||||
})
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.show()
|
notification.show()
|
||||||
|
|||||||
@@ -1,236 +1,236 @@
|
|||||||
import db, { GalleryDB } from '@core/datastore'
|
import db, { GalleryDB } from '@core/datastore'
|
||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
import uploader from 'apis/app/uploader'
|
import uploader from 'apis/app/uploader'
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
import { Notification, WebContents } from 'electron'
|
import { Notification, WebContents } from 'electron'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import { cloneDeep } from 'lodash-es'
|
import { cloneDeep } from 'lodash-es'
|
||||||
import type { IPicGo } from 'piclist'
|
import type { IPicGo } from 'piclist'
|
||||||
|
|
||||||
import type { IFileWithPath, ImgInfo, IStringKeyMap, IUploadOption } from '#/types/types'
|
import type { IFileWithPath, ImgInfo, IStringKeyMap, IUploadOption } from '#/types/types'
|
||||||
import { T as $t } from '~/i18n/index'
|
import { T as $t } from '~/i18n/index'
|
||||||
import { handleCopyUrl, handleUrlEncodeWithSetting } from '~/utils/common'
|
import { handleCopyUrl, handleUrlEncodeWithSetting } from '~/utils/common'
|
||||||
import { configPaths } from '~/utils/configPaths'
|
import { configPaths } from '~/utils/configPaths'
|
||||||
import { IPasteStyle, IWindowList } from '~/utils/enum'
|
import { IPasteStyle, IWindowList } from '~/utils/enum'
|
||||||
import { changeCurrentUploader } from '~/utils/handleUploaderConfig'
|
import { changeCurrentUploader } from '~/utils/handleUploaderConfig'
|
||||||
import pasteTemplate from '~/utils/pasteTemplate'
|
import pasteTemplate from '~/utils/pasteTemplate'
|
||||||
|
|
||||||
const handleClipboardUploading = async (): Promise<false | ImgInfo[]> => {
|
const handleClipboardUploading = async (): Promise<false | ImgInfo[]> => {
|
||||||
const useBuiltinClipboard =
|
const useBuiltinClipboard =
|
||||||
db.get(configPaths.settings.useBuiltinClipboard) === undefined
|
db.get(configPaths.settings.useBuiltinClipboard) === undefined
|
||||||
? true
|
? true
|
||||||
: !!db.get(configPaths.settings.useBuiltinClipboard)
|
: !!db.get(configPaths.settings.useBuiltinClipboard)
|
||||||
const win = windowManager.getAvailableWindow()
|
const win = windowManager.getAvailableWindow()
|
||||||
if (useBuiltinClipboard) {
|
if (useBuiltinClipboard) {
|
||||||
return await uploader.setWebContents(win!.webContents).uploadWithBuildInClipboard()
|
return await uploader.setWebContents(win!.webContents).uploadWithBuildInClipboard()
|
||||||
}
|
}
|
||||||
return await uploader.setWebContents(win!.webContents).upload()
|
return await uploader.setWebContents(win!.webContents).upload()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleClipboardUploadingReturnCtx = async (img?: IUploadOption, skipProcess = false): Promise<false | IPicGo> => {
|
const handleClipboardUploadingReturnCtx = async (img?: IUploadOption, skipProcess = false): Promise<false | IPicGo> => {
|
||||||
const useBuiltinClipboard =
|
const useBuiltinClipboard =
|
||||||
db.get(configPaths.settings.useBuiltinClipboard) === undefined
|
db.get(configPaths.settings.useBuiltinClipboard) === undefined
|
||||||
? true
|
? true
|
||||||
: !!db.get(configPaths.settings.useBuiltinClipboard)
|
: !!db.get(configPaths.settings.useBuiltinClipboard)
|
||||||
const win = windowManager.getAvailableWindow()
|
const win = windowManager.getAvailableWindow()
|
||||||
if (useBuiltinClipboard) {
|
if (useBuiltinClipboard) {
|
||||||
return await uploader.setWebContents(win!.webContents).uploadWithBuildInClipboardReturnCtx(img, skipProcess)
|
return await uploader.setWebContents(win!.webContents).uploadWithBuildInClipboardReturnCtx(img, skipProcess)
|
||||||
}
|
}
|
||||||
return await uploader.setWebContents(win!.webContents).uploadReturnCtx(img, skipProcess)
|
return await uploader.setWebContents(win!.webContents).uploadReturnCtx(img, skipProcess)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const uploadClipboardFiles = async (): Promise<IStringKeyMap> => {
|
export const uploadClipboardFiles = async (): Promise<IStringKeyMap> => {
|
||||||
const { needRestore, ctx } = await handleSecondaryUpload(undefined, undefined, 'clipboard')
|
const { needRestore, ctx } = await handleSecondaryUpload(undefined, undefined, 'clipboard')
|
||||||
let img: ImgInfo[] | false = false
|
let img: ImgInfo[] | false = false
|
||||||
if (needRestore) {
|
if (needRestore) {
|
||||||
const res = await handleClipboardUploadingReturnCtx(ctx ? ctx.processedInput : undefined, true)
|
const res = await handleClipboardUploadingReturnCtx(ctx ? ctx.processedInput : undefined, true)
|
||||||
img = res ? res.output : false
|
img = res ? res.output : false
|
||||||
} else {
|
} else {
|
||||||
img = await handleClipboardUploading()
|
img = await handleClipboardUploading()
|
||||||
}
|
}
|
||||||
if (img !== false) {
|
if (img !== false) {
|
||||||
if (img.length > 0) {
|
if (img.length > 0) {
|
||||||
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)
|
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)
|
||||||
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||||
const [pastedText, shortUrl] = await pasteTemplate(pasteStyle, img[0], db.get(configPaths.settings.customLink))
|
const [pastedText, shortUrl] = await pasteTemplate(pasteStyle, img[0], db.get(configPaths.settings.customLink))
|
||||||
img[0].shortUrl = shortUrl
|
img[0].shortUrl = shortUrl
|
||||||
handleCopyUrl(pastedText)
|
handleCopyUrl(pastedText)
|
||||||
const isShowResultNotification =
|
const isShowResultNotification =
|
||||||
db.get(configPaths.settings.uploadResultNotification) === undefined
|
db.get(configPaths.settings.uploadResultNotification) === undefined
|
||||||
? true
|
? true
|
||||||
: !!db.get(configPaths.settings.uploadResultNotification)
|
: !!db.get(configPaths.settings.uploadResultNotification)
|
||||||
if (isShowResultNotification) {
|
if (isShowResultNotification) {
|
||||||
const notification = new Notification({
|
const notification = new Notification({
|
||||||
title: $t('UPLOAD_SUCCEED'),
|
title: $t('UPLOAD_SUCCEED'),
|
||||||
body: shortUrl || img[0].imgUrl!
|
body: shortUrl || img[0].imgUrl!
|
||||||
// icon: img[0].imgUrl
|
// icon: img[0].imgUrl
|
||||||
})
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.show()
|
notification.show()
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
const inserted = await GalleryDB.getInstance().insert(img[0])
|
const inserted = await GalleryDB.getInstance().insert(img[0])
|
||||||
// trayWindow just be created in mac/windows, not in linux
|
// trayWindow just be created in mac/windows, not in linux
|
||||||
trayWindow?.webContents?.send('clipboardFiles', [])
|
trayWindow?.webContents?.send('clipboardFiles', [])
|
||||||
trayWindow?.webContents?.send('uploadFiles', img)
|
trayWindow?.webContents?.send('uploadFiles', img)
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
url: handleUrlEncodeWithSetting(inserted.imgUrl as string),
|
url: handleUrlEncodeWithSetting(inserted.imgUrl as string),
|
||||||
fullResult: inserted
|
fullResult: inserted
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const notification = new Notification({
|
const notification = new Notification({
|
||||||
title: $t('UPLOAD_FAILED'),
|
title: $t('UPLOAD_FAILED'),
|
||||||
body: $t('TIPS_UPLOAD_NOT_PICTURES')
|
body: $t('TIPS_UPLOAD_NOT_PICTURES')
|
||||||
})
|
})
|
||||||
notification.show()
|
notification.show()
|
||||||
return {
|
return {
|
||||||
url: '',
|
url: '',
|
||||||
fullResult: {}
|
fullResult: {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
url: '',
|
url: '',
|
||||||
fullResult: {}
|
fullResult: {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const uploadChoosedFiles = async (
|
export const uploadChoosedFiles = async (
|
||||||
webContents: WebContents,
|
webContents: WebContents,
|
||||||
files: IFileWithPath[]
|
files: IFileWithPath[]
|
||||||
): Promise<IStringKeyMap[]> => {
|
): Promise<IStringKeyMap[]> => {
|
||||||
const input = files.map(item => item.path)
|
const input = files.map(item => item.path)
|
||||||
const rawInput = cloneDeep(input)
|
const rawInput = cloneDeep(input)
|
||||||
const { needRestore, ctx } = await handleSecondaryUpload(webContents, input)
|
const { needRestore, ctx } = await handleSecondaryUpload(webContents, input)
|
||||||
let imgs: ImgInfo[] | false = false
|
let imgs: ImgInfo[] | false = false
|
||||||
if (needRestore) {
|
if (needRestore) {
|
||||||
const res = await uploader.setWebContents(webContents).uploadReturnCtx(ctx ? ctx.processedInput : input, true)
|
const res = await uploader.setWebContents(webContents).uploadReturnCtx(ctx ? ctx.processedInput : input, true)
|
||||||
imgs = res ? res.output : false
|
imgs = res ? res.output : false
|
||||||
} else {
|
} else {
|
||||||
imgs = await uploader.setWebContents(webContents).upload(input)
|
imgs = await uploader.setWebContents(webContents).upload(input)
|
||||||
}
|
}
|
||||||
const result = []
|
const result = []
|
||||||
if (imgs !== false) {
|
if (imgs !== false) {
|
||||||
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
const pasteStyle = db.get(configPaths.settings.pasteStyle) || IPasteStyle.MARKDOWN
|
||||||
const deleteLocalFile = db.get(configPaths.settings.deleteLocalFile) || false
|
const deleteLocalFile = db.get(configPaths.settings.deleteLocalFile) || false
|
||||||
const pasteText: string[] = []
|
const pasteText: string[] = []
|
||||||
for (let i = 0; i < imgs.length; i++) {
|
for (let i = 0; i < imgs.length; i++) {
|
||||||
if (deleteLocalFile) {
|
if (deleteLocalFile) {
|
||||||
fs.remove(rawInput[i])
|
fs.remove(rawInput[i])
|
||||||
.then(() => {
|
.then(() => {
|
||||||
picgo.log.info(`delete local file: ${rawInput[i]}`)
|
picgo.log.info(`delete local file: ${rawInput[i]}`)
|
||||||
})
|
})
|
||||||
.catch((err: Error) => {
|
.catch((err: Error) => {
|
||||||
picgo.log.error(err)
|
picgo.log.error(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const [pasteTextItem, shortUrl] = await pasteTemplate(
|
const [pasteTextItem, shortUrl] = await pasteTemplate(
|
||||||
pasteStyle,
|
pasteStyle,
|
||||||
imgs[i],
|
imgs[i],
|
||||||
db.get(configPaths.settings.customLink)
|
db.get(configPaths.settings.customLink)
|
||||||
)
|
)
|
||||||
imgs[i].shortUrl = shortUrl
|
imgs[i].shortUrl = shortUrl
|
||||||
pasteText.push(pasteTextItem)
|
pasteText.push(pasteTextItem)
|
||||||
const isShowResultNotification =
|
const isShowResultNotification =
|
||||||
db.get(configPaths.settings.uploadResultNotification) === undefined
|
db.get(configPaths.settings.uploadResultNotification) === undefined
|
||||||
? true
|
? true
|
||||||
: !!db.get(configPaths.settings.uploadResultNotification)
|
: !!db.get(configPaths.settings.uploadResultNotification)
|
||||||
if (isShowResultNotification) {
|
if (isShowResultNotification) {
|
||||||
const notification = new Notification({
|
const notification = new Notification({
|
||||||
title: $t('UPLOAD_SUCCEED'),
|
title: $t('UPLOAD_SUCCEED'),
|
||||||
body: shortUrl || imgs[i].imgUrl!
|
body: shortUrl || imgs[i].imgUrl!
|
||||||
// icon: files[i].path
|
// icon: files[i].path
|
||||||
})
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.show()
|
notification.show()
|
||||||
}, i * 100)
|
}, i * 100)
|
||||||
}
|
}
|
||||||
const inserted = await GalleryDB.getInstance().insert(imgs[i])
|
const inserted = await GalleryDB.getInstance().insert(imgs[i])
|
||||||
result.push({
|
result.push({
|
||||||
url: handleUrlEncodeWithSetting(inserted.imgUrl!),
|
url: handleUrlEncodeWithSetting(inserted.imgUrl!),
|
||||||
fullResult: inserted
|
fullResult: inserted
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
handleCopyUrl(pasteText.join('\n'))
|
handleCopyUrl(pasteText.join('\n'))
|
||||||
// trayWindow just be created in mac/windows, not in linux
|
// trayWindow just be created in mac/windows, not in linux
|
||||||
windowManager.get(IWindowList.TRAY_WINDOW)?.webContents?.send('uploadFiles', imgs)
|
windowManager.get(IWindowList.TRAY_WINDOW)?.webContents?.send('uploadFiles', imgs)
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
} else {
|
} else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const handleSecondaryUpload = async (
|
export const handleSecondaryUpload = async (
|
||||||
webContents?: WebContents,
|
webContents?: WebContents,
|
||||||
input?: string[],
|
input?: string[],
|
||||||
uploadType: 'clipboard' | 'file' | 'tray' = 'file'
|
uploadType: 'clipboard' | 'file' | 'tray' = 'file'
|
||||||
): Promise<{ needRestore: boolean; ctx: IPicGo | false }> => {
|
): Promise<{ needRestore: boolean; ctx: IPicGo | false }> => {
|
||||||
const enableSecondUploader = db.get(configPaths.settings.enableSecondUploader) || false
|
const enableSecondUploader = db.get(configPaths.settings.enableSecondUploader) || false
|
||||||
let currentPicBedType = ''
|
let currentPicBedType = ''
|
||||||
let currentPicBedConfig = {} as IStringKeyMap
|
let currentPicBedConfig = {} as IStringKeyMap
|
||||||
let currentPicBedConfigId = ''
|
let currentPicBedConfigId = ''
|
||||||
let needRestore = false
|
let needRestore = false
|
||||||
let ctx: IPicGo | false = false
|
let ctx: IPicGo | false = false
|
||||||
if (enableSecondUploader) {
|
if (enableSecondUploader) {
|
||||||
const secondUploader = db.get(configPaths.picBed.secondUploader)
|
const secondUploader = db.get(configPaths.picBed.secondUploader)
|
||||||
const secondUploaderConfig = db.get(configPaths.picBed.secondUploaderConfig)
|
const secondUploaderConfig = db.get(configPaths.picBed.secondUploaderConfig)
|
||||||
const secondUploaderId = db.get(configPaths.picBed.secondUploaderId)
|
const secondUploaderId = db.get(configPaths.picBed.secondUploaderId)
|
||||||
const currentPicBed = db.get('picBed') || ({} as IStringKeyMap)
|
const currentPicBed = db.get('picBed') || ({} as IStringKeyMap)
|
||||||
currentPicBedType = currentPicBed.uploader || currentPicBed.current || 'smms'
|
currentPicBedType = currentPicBed.uploader || currentPicBed.current || 'smms'
|
||||||
currentPicBedConfig = currentPicBed[currentPicBedType] || ({} as IStringKeyMap)
|
currentPicBedConfig = currentPicBed[currentPicBedType] || ({} as IStringKeyMap)
|
||||||
currentPicBedConfigId = currentPicBedConfig._id
|
currentPicBedConfigId = currentPicBedConfig._id
|
||||||
if (
|
if (
|
||||||
secondUploader === currentPicBedType &&
|
secondUploader === currentPicBedType &&
|
||||||
secondUploaderConfig._configName === currentPicBedConfig._configName &&
|
secondUploaderConfig._configName === currentPicBedConfig._configName &&
|
||||||
secondUploaderId === currentPicBedConfigId
|
secondUploaderId === currentPicBedConfigId
|
||||||
) {
|
) {
|
||||||
picgo.log.info('second uploader is the same as current uploader')
|
picgo.log.info('second uploader is the same as current uploader')
|
||||||
} else {
|
} else {
|
||||||
needRestore = true
|
needRestore = true
|
||||||
let secondImgs: ImgInfo[] | false = false
|
let secondImgs: ImgInfo[] | false = false
|
||||||
changeCurrentUploader(secondUploader, secondUploaderConfig, secondUploaderId)
|
changeCurrentUploader(secondUploader, secondUploaderConfig, secondUploaderId)
|
||||||
if (uploadType === 'clipboard') {
|
if (uploadType === 'clipboard') {
|
||||||
ctx = await handleClipboardUploadingReturnCtx(undefined)
|
ctx = await handleClipboardUploadingReturnCtx(undefined)
|
||||||
} else {
|
} else {
|
||||||
ctx = await uploader.setWebContents(webContents!).uploadReturnCtx(input)
|
ctx = await uploader.setWebContents(webContents!).uploadReturnCtx(input)
|
||||||
}
|
}
|
||||||
secondImgs = ctx ? ctx.output : false
|
secondImgs = ctx ? ctx.output : false
|
||||||
if (secondImgs !== false) {
|
if (secondImgs !== false) {
|
||||||
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)
|
const trayWindow = windowManager.get(IWindowList.TRAY_WINDOW)
|
||||||
if (uploadType === 'clipboard') {
|
if (uploadType === 'clipboard') {
|
||||||
if (secondImgs.length > 0) {
|
if (secondImgs.length > 0) {
|
||||||
await GalleryDB.getInstance().insert(secondImgs[0])
|
await GalleryDB.getInstance().insert(secondImgs[0])
|
||||||
trayWindow?.webContents?.send('clipboardFiles', [])
|
trayWindow?.webContents?.send('clipboardFiles', [])
|
||||||
trayWindow?.webContents?.send('uploadFiles', secondImgs)
|
trayWindow?.webContents?.send('uploadFiles', secondImgs)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const secondImgsItem of secondImgs) {
|
for (const secondImgsItem of secondImgs) {
|
||||||
await GalleryDB.getInstance().insert(secondImgsItem)
|
await GalleryDB.getInstance().insert(secondImgsItem)
|
||||||
}
|
}
|
||||||
if (uploadType === 'tray') {
|
if (uploadType === 'tray') {
|
||||||
trayWindow?.webContents?.send('dragFiles', secondImgs)
|
trayWindow?.webContents?.send('dragFiles', secondImgs)
|
||||||
} else {
|
} else {
|
||||||
trayWindow?.webContents?.send('uploadFiles', secondImgs)
|
trayWindow?.webContents?.send('uploadFiles', secondImgs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW) && uploadType !== 'tray') {
|
if (windowManager.has(IWindowList.SETTING_WINDOW) && uploadType !== 'tray') {
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents?.send('updateGallery')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (needRestore) {
|
if (needRestore) {
|
||||||
changeCurrentUploader(currentPicBedType, currentPicBedConfig, currentPicBedConfigId)
|
changeCurrentUploader(currentPicBedType, currentPicBedConfig, currentPicBedConfigId)
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
needRestore,
|
needRestore,
|
||||||
ctx
|
ctx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,11 +36,11 @@ const waitForRename = (window: BrowserWindow, id: number): Promise<string | null
|
|||||||
class Uploader {
|
class Uploader {
|
||||||
private webContents: WebContents | null = null
|
private webContents: WebContents | null = null
|
||||||
|
|
||||||
constructor () {
|
constructor() {
|
||||||
this.init()
|
this.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
init () {
|
init() {
|
||||||
picgo.on(ICOREBuildInEvent.NOTIFICATION, (message: any) => {
|
picgo.on(ICOREBuildInEvent.NOTIFICATION, (message: any) => {
|
||||||
new Notification(message).show()
|
new Notification(message).show()
|
||||||
})
|
})
|
||||||
@@ -92,12 +92,12 @@ class Uploader {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
setWebContents (webContents: WebContents) {
|
setWebContents(webContents: WebContents) {
|
||||||
this.webContents = webContents
|
this.webContents = webContents
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getClipboardImagePath (): Promise<string | false> {
|
private async getClipboardImagePath(): Promise<string | false> {
|
||||||
const imgPath = getClipboardFilePath()
|
const imgPath = getClipboardFilePath()
|
||||||
if (imgPath) return imgPath
|
if (imgPath) return imgPath
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ class Uploader {
|
|||||||
/**
|
/**
|
||||||
* use electron's clipboard image to upload
|
* use electron's clipboard image to upload
|
||||||
*/
|
*/
|
||||||
async uploadWithBuildInClipboard (): Promise<ImgInfo[] | false> {
|
async uploadWithBuildInClipboard(): Promise<ImgInfo[] | false> {
|
||||||
let imgPath: string | false = false
|
let imgPath: string | false = false
|
||||||
try {
|
try {
|
||||||
imgPath = await this.getClipboardImagePath()
|
imgPath = await this.getClipboardImagePath()
|
||||||
@@ -131,7 +131,7 @@ class Uploader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async uploadWithBuildInClipboardReturnCtx (img?: IUploadOption, skipProcess = false): Promise<IPicGo | false> {
|
async uploadWithBuildInClipboardReturnCtx(img?: IUploadOption, skipProcess = false): Promise<IPicGo | false> {
|
||||||
let imgPath: string | false = false
|
let imgPath: string | false = false
|
||||||
try {
|
try {
|
||||||
imgPath = await this.getClipboardImagePath()
|
imgPath = await this.getClipboardImagePath()
|
||||||
@@ -147,7 +147,7 @@ class Uploader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async uploadReturnCtx (img?: IUploadOption, skipProcess = false): Promise<IPicGo | false> {
|
async uploadReturnCtx(img?: IUploadOption, skipProcess = false): Promise<IPicGo | false> {
|
||||||
try {
|
try {
|
||||||
const ctx = await picgo.uploadReturnCtx(img, skipProcess)
|
const ctx = await picgo.uploadReturnCtx(img, skipProcess)
|
||||||
if (!Array.isArray(ctx.output) || !ctx.output.some((item: ImgInfo) => item.imgUrl)) return false
|
if (!Array.isArray(ctx.output) || !ctx.output.some((item: ImgInfo) => item.imgUrl)) return false
|
||||||
@@ -172,7 +172,7 @@ class Uploader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async upload (img?: IUploadOption): Promise<ImgInfo[] | false> {
|
async upload(img?: IUploadOption): Promise<ImgInfo[] | false> {
|
||||||
try {
|
try {
|
||||||
const output = await picgo.upload(img)
|
const output = await picgo.upload(img)
|
||||||
if (!Array.isArray(output) || !output.some((item: ImgInfo) => item.imgUrl)) return false
|
if (!Array.isArray(output) || !output.some((item: ImgInfo) => item.imgUrl)) return false
|
||||||
|
|||||||
@@ -1,277 +1,277 @@
|
|||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
import bus from '@core/bus'
|
import bus from '@core/bus'
|
||||||
import { CREATE_APP_MENU } from '@core/bus/constants'
|
import { CREATE_APP_MENU } from '@core/bus/constants'
|
||||||
import db from '@core/datastore'
|
import db from '@core/datastore'
|
||||||
import { app, BrowserWindow, Rectangle } from 'electron'
|
import { app, BrowserWindow, Rectangle } from 'electron'
|
||||||
|
|
||||||
import type { IWindowListItem } from '#/types/electron'
|
import type { IWindowListItem } from '#/types/electron'
|
||||||
import type { IBrowserWindowOptions } from '#/types/types'
|
import type { IBrowserWindowOptions } from '#/types/types'
|
||||||
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '~/events/constant'
|
import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '~/events/constant'
|
||||||
import { T as $t } from '~/i18n'
|
import { T as $t } from '~/i18n'
|
||||||
import { configPaths } from '~/utils/configPaths'
|
import { configPaths } from '~/utils/configPaths'
|
||||||
import { IWindowList } from '~/utils/enum'
|
import { IWindowList } from '~/utils/enum'
|
||||||
|
|
||||||
import logo from '../../../../../resources/logo.png?asset&asarUnpack'
|
import logo from '../../../../../resources/logo.png?asset&asarUnpack'
|
||||||
|
|
||||||
const windowList = new Map<string, IWindowListItem>()
|
const windowList = new Map<string, IWindowListItem>()
|
||||||
|
|
||||||
const getDefaultWindowSizes = (): { width: number; height: number } => {
|
const getDefaultWindowSizes = (): { width: number; height: number } => {
|
||||||
const [mainWindowWidth, mainWindowHeight] = db.get([
|
const [mainWindowWidth, mainWindowHeight] = db.get([
|
||||||
configPaths.settings.mainWindowWidth,
|
configPaths.settings.mainWindowWidth,
|
||||||
configPaths.settings.mainWindowHeight
|
configPaths.settings.mainWindowHeight
|
||||||
])
|
])
|
||||||
return {
|
return {
|
||||||
width: mainWindowWidth || 1200,
|
width: mainWindowWidth || 1200,
|
||||||
height: mainWindowHeight || 800
|
height: mainWindowHeight || 800
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setMiniWindowShape (win: BrowserWindow) {
|
function setMiniWindowShape(win: BrowserWindow) {
|
||||||
const radius = 32
|
const radius = 32
|
||||||
const shape: Rectangle[] = []
|
const shape: Rectangle[] = []
|
||||||
|
|
||||||
for (let y = -radius; y <= radius; y++) {
|
for (let y = -radius; y <= radius; y++) {
|
||||||
for (let x = -radius; x <= radius; x++) {
|
for (let x = -radius; x <= radius; x++) {
|
||||||
if (x * x + y * y <= radius * radius) {
|
if (x * x + y * y <= radius * radius) {
|
||||||
shape.push({ x: radius + x, y: radius + y, width: 1, height: 1 })
|
shape.push({ x: radius + x, y: radius + y, width: 1, height: 1 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
win.setShape(shape)
|
win.setShape(shape)
|
||||||
}
|
}
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||||
const preloadPath = fileURLToPath(new URL('../preload/index.mjs', import.meta.url))
|
const preloadPath = fileURLToPath(new URL('../preload/index.mjs', import.meta.url))
|
||||||
|
|
||||||
const { width: defaultWindowWidth, height: defaultWindowHeight } = getDefaultWindowSizes()
|
const { width: defaultWindowWidth, height: defaultWindowHeight } = getDefaultWindowSizes()
|
||||||
|
|
||||||
const trayWindowOptions = {
|
const trayWindowOptions = {
|
||||||
height: 350,
|
height: 350,
|
||||||
width: 196,
|
width: 196,
|
||||||
show: false,
|
show: false,
|
||||||
frame: false,
|
frame: false,
|
||||||
fullscreenable: false,
|
fullscreenable: false,
|
||||||
resizable: false,
|
resizable: false,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
vibrancy: 'ultra-dark',
|
vibrancy: 'ultra-dark',
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
preload: preloadPath,
|
preload: preloadPath,
|
||||||
nodeIntegration: false,
|
nodeIntegration: false,
|
||||||
contextIsolation: true,
|
contextIsolation: true,
|
||||||
nodeIntegrationInWorker: false,
|
nodeIntegrationInWorker: false,
|
||||||
backgroundThrottling: true,
|
backgroundThrottling: true,
|
||||||
webSecurity: false
|
webSecurity: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const settingWindowOptions = {
|
const settingWindowOptions = {
|
||||||
height: defaultWindowHeight,
|
height: defaultWindowHeight,
|
||||||
width: defaultWindowWidth,
|
width: defaultWindowWidth,
|
||||||
show: false,
|
show: false,
|
||||||
frame: true,
|
frame: true,
|
||||||
center: true,
|
center: true,
|
||||||
fullscreenable: true,
|
fullscreenable: true,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
title: 'PicList',
|
title: 'PicList',
|
||||||
transparent: false,
|
transparent: false,
|
||||||
backgroundColor: '#ebeef5',
|
backgroundColor: '#ebeef5',
|
||||||
titleBarStyle: 'hidden',
|
titleBarStyle: 'hidden',
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
webviewTag: true,
|
webviewTag: true,
|
||||||
backgroundThrottling: true,
|
backgroundThrottling: true,
|
||||||
preload: preloadPath,
|
preload: preloadPath,
|
||||||
nodeIntegration: false,
|
nodeIntegration: false,
|
||||||
contextIsolation: true,
|
contextIsolation: true,
|
||||||
nodeIntegrationInWorker: false,
|
nodeIntegrationInWorker: false,
|
||||||
webSecurity: false
|
webSecurity: false
|
||||||
}
|
}
|
||||||
} as IBrowserWindowOptions
|
} as IBrowserWindowOptions
|
||||||
|
|
||||||
if (process.platform !== 'darwin') {
|
if (process.platform !== 'darwin') {
|
||||||
settingWindowOptions.frame = false
|
settingWindowOptions.frame = false
|
||||||
settingWindowOptions.icon = logo
|
settingWindowOptions.icon = logo
|
||||||
}
|
}
|
||||||
|
|
||||||
const miniWindowOptions = {
|
const miniWindowOptions = {
|
||||||
height: 64,
|
height: 64,
|
||||||
width: 64,
|
width: 64,
|
||||||
show: process.platform === 'linux',
|
show: process.platform === 'linux',
|
||||||
frame: false,
|
frame: false,
|
||||||
fullscreenable: false,
|
fullscreenable: false,
|
||||||
skipTaskbar: true,
|
skipTaskbar: true,
|
||||||
resizable: false,
|
resizable: false,
|
||||||
transparent: process.platform !== 'linux',
|
transparent: process.platform !== 'linux',
|
||||||
icon: logo,
|
icon: logo,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
preload: preloadPath,
|
preload: preloadPath,
|
||||||
nodeIntegration: false,
|
nodeIntegration: false,
|
||||||
contextIsolation: true,
|
contextIsolation: true,
|
||||||
backgroundThrottling: true,
|
backgroundThrottling: true,
|
||||||
nodeIntegrationInWorker: false
|
nodeIntegrationInWorker: false
|
||||||
}
|
}
|
||||||
} as IBrowserWindowOptions
|
} as IBrowserWindowOptions
|
||||||
|
|
||||||
if (db.get(configPaths.settings.miniWindowOntop)) {
|
if (db.get(configPaths.settings.miniWindowOntop)) {
|
||||||
miniWindowOptions.alwaysOnTop = true
|
miniWindowOptions.alwaysOnTop = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const renameWindowOptions = {
|
const renameWindowOptions = {
|
||||||
height: 270,
|
height: 270,
|
||||||
width: 350,
|
width: 350,
|
||||||
show: true,
|
show: true,
|
||||||
fullscreenable: false,
|
fullscreenable: false,
|
||||||
icon: logo,
|
icon: logo,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
preload: preloadPath,
|
preload: preloadPath,
|
||||||
nodeIntegration: false,
|
nodeIntegration: false,
|
||||||
contextIsolation: true,
|
contextIsolation: true,
|
||||||
nodeIntegrationInWorker: false,
|
nodeIntegrationInWorker: false,
|
||||||
backgroundThrottling: false
|
backgroundThrottling: false
|
||||||
}
|
}
|
||||||
} as IBrowserWindowOptions
|
} as IBrowserWindowOptions
|
||||||
|
|
||||||
if (process.platform !== 'darwin') {
|
if (process.platform !== 'darwin') {
|
||||||
renameWindowOptions.show = true
|
renameWindowOptions.show = true
|
||||||
renameWindowOptions.backgroundColor = '#3f3c37'
|
renameWindowOptions.backgroundColor = '#3f3c37'
|
||||||
renameWindowOptions.autoHideMenuBar = true
|
renameWindowOptions.autoHideMenuBar = true
|
||||||
renameWindowOptions.transparent = false
|
renameWindowOptions.transparent = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const toolboxWindowOptions = {
|
const toolboxWindowOptions = {
|
||||||
height: 450,
|
height: 450,
|
||||||
width: 800,
|
width: 800,
|
||||||
show: false,
|
show: false,
|
||||||
frame: true,
|
frame: true,
|
||||||
center: true,
|
center: true,
|
||||||
fullscreenable: false,
|
fullscreenable: false,
|
||||||
resizable: false,
|
resizable: false,
|
||||||
title: `PicList ${$t('TOOLBOX')}`,
|
title: `PicList ${$t('TOOLBOX')}`,
|
||||||
backgroundColor: '#ebeef5',
|
backgroundColor: '#ebeef5',
|
||||||
icon: logo,
|
icon: logo,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
backgroundThrottling: true,
|
backgroundThrottling: true,
|
||||||
preload: preloadPath,
|
preload: preloadPath,
|
||||||
nodeIntegration: false,
|
nodeIntegration: false,
|
||||||
contextIsolation: true,
|
contextIsolation: true,
|
||||||
nodeIntegrationInWorker: false,
|
nodeIntegrationInWorker: false,
|
||||||
webSecurity: false
|
webSecurity: false
|
||||||
}
|
}
|
||||||
} as IBrowserWindowOptions
|
} as IBrowserWindowOptions
|
||||||
|
|
||||||
if (process.platform !== 'darwin') {
|
if (process.platform !== 'darwin') {
|
||||||
toolboxWindowOptions.backgroundColor = '#3f3c37'
|
toolboxWindowOptions.backgroundColor = '#3f3c37'
|
||||||
toolboxWindowOptions.autoHideMenuBar = true
|
toolboxWindowOptions.autoHideMenuBar = true
|
||||||
toolboxWindowOptions.transparent = false
|
toolboxWindowOptions.transparent = false
|
||||||
}
|
}
|
||||||
|
|
||||||
windowList.set(IWindowList.TRAY_WINDOW, {
|
windowList.set(IWindowList.TRAY_WINDOW, {
|
||||||
isValid: process.platform !== 'linux',
|
isValid: process.platform !== 'linux',
|
||||||
multiple: false,
|
multiple: false,
|
||||||
options: () => trayWindowOptions,
|
options: () => trayWindowOptions,
|
||||||
callback (window) {
|
callback(window) {
|
||||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||||
window.loadURL(process.env.ELECTRON_RENDERER_URL)
|
window.loadURL(process.env.ELECTRON_RENDERER_URL)
|
||||||
} else {
|
} else {
|
||||||
window.loadFile(path.join(__dirname, '../renderer/index.html'))
|
window.loadFile(path.join(__dirname, '../renderer/index.html'))
|
||||||
}
|
}
|
||||||
window.on('blur', () => {
|
window.on('blur', () => {
|
||||||
window.hide()
|
window.hide()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
windowList.set(IWindowList.SETTING_WINDOW, {
|
windowList.set(IWindowList.SETTING_WINDOW, {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
options: () => settingWindowOptions,
|
options: () => settingWindowOptions,
|
||||||
callback (window, windowManager) {
|
callback(window, windowManager) {
|
||||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||||
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#main-page/upload`)
|
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#main-page/upload`)
|
||||||
} else {
|
} else {
|
||||||
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
||||||
hash: 'main-page/upload'
|
hash: 'main-page/upload'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
window.on('closed', () => {
|
window.on('closed', () => {
|
||||||
bus.emit(TOGGLE_SHORTKEY_MODIFIED_MODE, false)
|
bus.emit(TOGGLE_SHORTKEY_MODIFIED_MODE, false)
|
||||||
if (process.platform === 'linux') {
|
if (process.platform === 'linux') {
|
||||||
process.nextTick(() => {
|
process.nextTick(() => {
|
||||||
app.quit()
|
app.quit()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
bus.emit(CREATE_APP_MENU)
|
bus.emit(CREATE_APP_MENU)
|
||||||
windowManager.create(IWindowList.MINI_WINDOW)
|
windowManager.create(IWindowList.MINI_WINDOW)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
windowList.set(IWindowList.MINI_WINDOW, {
|
windowList.set(IWindowList.MINI_WINDOW, {
|
||||||
isValid: process.platform !== 'darwin',
|
isValid: process.platform !== 'darwin',
|
||||||
multiple: false,
|
multiple: false,
|
||||||
options: () => miniWindowOptions,
|
options: () => miniWindowOptions,
|
||||||
callback (window) {
|
callback(window) {
|
||||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||||
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#mini-page`)
|
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#mini-page`)
|
||||||
} else {
|
} else {
|
||||||
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
||||||
hash: 'mini-page'
|
hash: 'mini-page'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
setMiniWindowShape(window)
|
setMiniWindowShape(window)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
windowList.set(IWindowList.RENAME_WINDOW, {
|
windowList.set(IWindowList.RENAME_WINDOW, {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
options: () => renameWindowOptions,
|
options: () => renameWindowOptions,
|
||||||
async callback (window, windowManager) {
|
async callback(window, windowManager) {
|
||||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||||
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#rename-page`)
|
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#rename-page`)
|
||||||
} else {
|
} else {
|
||||||
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
||||||
hash: 'rename-page'
|
hash: 'rename-page'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const currentWindow = windowManager.getAvailableWindow(true)
|
const currentWindow = windowManager.getAvailableWindow(true)
|
||||||
if (currentWindow && currentWindow.isVisible()) {
|
if (currentWindow && currentWindow.isVisible()) {
|
||||||
const { x, y, width, height } = currentWindow.getBounds()
|
const { x, y, width, height } = currentWindow.getBounds()
|
||||||
const positionX = Math.floor(x + width / 2 - 150)
|
const positionX = Math.floor(x + width / 2 - 150)
|
||||||
const positionY = Math.floor(y + height / 2 - (height > 400 ? 88 : 0))
|
const positionY = Math.floor(y + height / 2 - (height > 400 ? 88 : 0))
|
||||||
window.setPosition(positionX, positionY, false)
|
window.setPosition(positionX, positionY, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
windowList.set(IWindowList.TOOLBOX_WINDOW, {
|
windowList.set(IWindowList.TOOLBOX_WINDOW, {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
options: () => toolboxWindowOptions,
|
options: () => toolboxWindowOptions,
|
||||||
async callback (window, windowManager) {
|
async callback(window, windowManager) {
|
||||||
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) {
|
||||||
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#toolbox-page`)
|
window.loadURL(`${process.env.ELECTRON_RENDERER_URL}#toolbox-page`)
|
||||||
} else {
|
} else {
|
||||||
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
window.loadFile(path.join(__dirname, '../renderer/index.html'), {
|
||||||
hash: 'toolbox-page'
|
hash: 'toolbox-page'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const currentWindow = windowManager.getAvailableWindow(true)
|
const currentWindow = windowManager.getAvailableWindow(true)
|
||||||
if (currentWindow && currentWindow.isVisible()) {
|
if (currentWindow && currentWindow.isVisible()) {
|
||||||
const { x, y, width, height } = currentWindow.getBounds()
|
const { x, y, width, height } = currentWindow.getBounds()
|
||||||
const positionX = Math.floor(x + width / 2 - 400)
|
const positionX = Math.floor(x + width / 2 - 400)
|
||||||
const positionY = Math.floor(y + height / 2 - (height > 400 ? 225 : 0))
|
const positionY = Math.floor(y + height / 2 - (height > 400 ? 225 : 0))
|
||||||
window.setPosition(positionX, positionY, false)
|
window.setPosition(positionX, positionY, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export default windowList
|
export default windowList
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import type { IWindowListItem, IWindowManager } from '#/types/electron'
|
|||||||
import { IWindowList } from '~/utils/enum'
|
import { IWindowList } from '~/utils/enum'
|
||||||
|
|
||||||
class WindowManager implements IWindowManager {
|
class WindowManager implements IWindowManager {
|
||||||
#windowMap: Map< string, BrowserWindow> = new Map()
|
#windowMap: Map<string, BrowserWindow> = new Map()
|
||||||
#windowIdMap: Map<number, string> = new Map()
|
#windowIdMap: Map<number, string> = new Map()
|
||||||
|
|
||||||
create (name: string) {
|
create(name: string) {
|
||||||
const windowConfig: IWindowListItem = windowList.get(name)!
|
const windowConfig: IWindowListItem = windowList.get(name)!
|
||||||
if (!windowConfig.isValid) return null
|
if (!windowConfig.isValid) return null
|
||||||
|
|
||||||
@@ -30,14 +30,14 @@ class WindowManager implements IWindowManager {
|
|||||||
return window
|
return window
|
||||||
}
|
}
|
||||||
|
|
||||||
get (name: string) {
|
get(name: string) {
|
||||||
if (this.has(name)) {
|
if (this.has(name)) {
|
||||||
return this.#windowMap.get(name)!
|
return this.#windowMap.get(name)!
|
||||||
}
|
}
|
||||||
return this.create(name)
|
return this.create(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
has (name: string) {
|
has(name: string) {
|
||||||
return this.#windowMap.has(name)
|
return this.#windowMap.has(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ class WindowManager implements IWindowManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getAvailableWindow (isSkipMiniWindow = false) {
|
getAvailableWindow(isSkipMiniWindow = false) {
|
||||||
const miniWindow = this.#windowMap.get(IWindowList.MINI_WINDOW)
|
const miniWindow = this.#windowMap.get(IWindowList.MINI_WINDOW)
|
||||||
if (miniWindow && miniWindow.isVisible() && !isSkipMiniWindow) {
|
if (miniWindow && miniWindow.isVisible() && !isSkipMiniWindow) {
|
||||||
return miniWindow
|
return miniWindow
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
import { EventEmitter } from 'node:events'
|
import { EventEmitter } from 'node:events'
|
||||||
|
|
||||||
class OptimizedBus extends EventEmitter {
|
class OptimizedBus extends EventEmitter {
|
||||||
constructor () {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
this.setMaxListeners(50)
|
this.setMaxListeners(50)
|
||||||
}
|
}
|
||||||
|
|
||||||
once (event: string | symbol, listener: (...args: any[]) => void): this {
|
once(event: string | symbol, listener: (...args: any[]) => void): this {
|
||||||
const wrappedListener = (...args: any[]) => {
|
const wrappedListener = (...args: any[]) => {
|
||||||
try {
|
try {
|
||||||
listener(...args)
|
listener(...args)
|
||||||
} finally {
|
} finally {
|
||||||
this.removeListener(event, wrappedListener)
|
this.removeListener(event, wrappedListener)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.once(event, wrappedListener)
|
return super.once(event, wrappedListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanupListeners () {
|
cleanupListeners() {
|
||||||
const events = this.eventNames()
|
const events = this.eventNames()
|
||||||
events.forEach(event => {
|
events.forEach(event => {
|
||||||
const listenerCount = this.listenerCount(event)
|
const listenerCount = this.listenerCount(event)
|
||||||
console.log(` listener count (${listenerCount}) for event: ${String(event)}`)
|
console.log(` listener count (${listenerCount}) for event: ${String(event)}`)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const bus = new OptimizedBus()
|
const bus = new OptimizedBus()
|
||||||
|
|
||||||
export default bus
|
export default bus
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const errorMsg = {
|
|||||||
brokenButBackup: $t('TIPS_PICGO_CONFIG_FILE_BROKEN_WITH_BACKUP')
|
brokenButBackup: $t('TIPS_PICGO_CONFIG_FILE_BROKEN_WITH_BACKUP')
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbChecker () {
|
function dbChecker() {
|
||||||
if (process.type !== 'renderer') {
|
if (process.type !== 'renderer') {
|
||||||
// db save bak
|
// db save bak
|
||||||
try {
|
try {
|
||||||
@@ -80,7 +80,7 @@ function dbChecker () {
|
|||||||
/**
|
/**
|
||||||
* Get config path
|
* Get config path
|
||||||
*/
|
*/
|
||||||
function dbPathChecker (): string {
|
function dbPathChecker(): string {
|
||||||
if (_configFilePath) {
|
if (_configFilePath) {
|
||||||
return _configFilePath
|
return _configFilePath
|
||||||
}
|
}
|
||||||
@@ -120,11 +120,11 @@ function dbPathChecker (): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbPathDir () {
|
function dbPathDir() {
|
||||||
return path.dirname(dbPathChecker())
|
return path.dirname(dbPathChecker())
|
||||||
}
|
}
|
||||||
|
|
||||||
function getGalleryDBPath (): {
|
function getGalleryDBPath(): {
|
||||||
dbPath: string
|
dbPath: string
|
||||||
dbBackupPath: string
|
dbBackupPath: string
|
||||||
} {
|
} {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export const DB_PATH: string = getGalleryDBPath().dbPath
|
|||||||
class ConfigStore {
|
class ConfigStore {
|
||||||
#db: JSONStore
|
#db: JSONStore
|
||||||
|
|
||||||
constructor () {
|
constructor() {
|
||||||
this.#db = new JSONStore(CONFIG_PATH)
|
this.#db = new JSONStore(CONFIG_PATH)
|
||||||
|
|
||||||
if (!this.#db.has('picBed')) {
|
if (!this.#db.has('picBed')) {
|
||||||
@@ -43,11 +43,11 @@ class ConfigStore {
|
|||||||
this.read()
|
this.read()
|
||||||
}
|
}
|
||||||
|
|
||||||
read (flush?: boolean): IJSON {
|
read(flush?: boolean): IJSON {
|
||||||
return this.#db.read(flush)
|
return this.#db.read(flush)
|
||||||
}
|
}
|
||||||
|
|
||||||
getSingle (key = ''): any {
|
getSingle(key = ''): any {
|
||||||
if (key === '') {
|
if (key === '') {
|
||||||
return this.#db.read(true)
|
return this.#db.read(true)
|
||||||
}
|
}
|
||||||
@@ -55,43 +55,43 @@ class ConfigStore {
|
|||||||
return this.#db.get(key)
|
return this.#db.get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
get (key: string): any
|
get(key: string): any
|
||||||
get (key: string[]): any[]
|
get(key: string[]): any[]
|
||||||
get (key: string | string[] = ''): any {
|
get(key: string | string[] = ''): any {
|
||||||
if (Array.isArray(key)) {
|
if (Array.isArray(key)) {
|
||||||
return key.map(k => this.getSingle(k))
|
return key.map(k => this.getSingle(k))
|
||||||
}
|
}
|
||||||
return this.getSingle(key)
|
return this.getSingle(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
set (key: string, value: any): void {
|
set(key: string, value: any): void {
|
||||||
this.read(true)
|
this.read(true)
|
||||||
return this.#db.set(key, value)
|
return this.#db.set(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
has (key: string) {
|
has(key: string) {
|
||||||
this.read(true)
|
this.read(true)
|
||||||
return this.#db.has(key)
|
return this.#db.has(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
unset (key: string, value: any): boolean {
|
unset(key: string, value: any): boolean {
|
||||||
this.read(true)
|
this.read(true)
|
||||||
return this.#db.unset(key, value)
|
return this.#db.unset(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
saveConfig (config: Partial<IConfig>): void {
|
saveConfig(config: Partial<IConfig>): void {
|
||||||
Object.keys(config).forEach((name: string) => {
|
Object.keys(config).forEach((name: string) => {
|
||||||
this.set(name, config[name])
|
this.set(name, config[name])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
removeConfig (config: IConfig): void {
|
removeConfig(config: IConfig): void {
|
||||||
Object.keys(config).forEach((name: string) => {
|
Object.keys(config).forEach((name: string) => {
|
||||||
this.unset(name, config[name])
|
this.unset(name, config[name])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getConfigPath () {
|
getConfigPath() {
|
||||||
return CONFIG_PATH
|
return CONFIG_PATH
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,11 +103,11 @@ export default db
|
|||||||
// v2.3.0 add gallery db
|
// v2.3.0 add gallery db
|
||||||
class GalleryDB {
|
class GalleryDB {
|
||||||
static #instance: DBStore
|
static #instance: DBStore
|
||||||
private constructor () {
|
private constructor() {
|
||||||
console.log('init gallery db')
|
console.log('init gallery db')
|
||||||
}
|
}
|
||||||
|
|
||||||
static getInstance (): DBStore {
|
static getInstance(): DBStore {
|
||||||
if (!GalleryDB.#instance) {
|
if (!GalleryDB.#instance) {
|
||||||
GalleryDB.#instance = new DBStore(DB_PATH, 'gallery')
|
GalleryDB.#instance = new DBStore(DB_PATH, 'gallery')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ picgo.GUI_VERSION = pkg.version
|
|||||||
|
|
||||||
const originPicGoSaveConfig = picgo.saveConfig.bind(picgo)
|
const originPicGoSaveConfig = picgo.saveConfig.bind(picgo)
|
||||||
|
|
||||||
function flushDB () {
|
function flushDB() {
|
||||||
db.read(true)
|
db.read(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ interface IConfigMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class AlistApi {
|
export default class AlistApi {
|
||||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||||
const { fileName, config } = configMap
|
const { fileName, config } = configMap
|
||||||
try {
|
try {
|
||||||
const { version, url, uploadPath, token } = config
|
const { version, url, uploadPath, token } = config
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const getAListToken = async (url: string, username: string, password: string) =>
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class AListplistApi {
|
export default class AListplistApi {
|
||||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||||
const { fileName, config } = configMap
|
const { fileName, config } = configMap
|
||||||
try {
|
try {
|
||||||
const { url, username, password, uploadPath } = config
|
const { url, username, password, uploadPath } = config
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ interface IConfigMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class AliyunApi {
|
export default class AliyunApi {
|
||||||
static #getKey (fileName: string, path?: string): string {
|
static #getKey(fileName: string, path?: string): string {
|
||||||
return path && path !== '/' ? `${path.replace(/^\/+|\/+$/, '')}/${fileName}` : fileName
|
return path && path !== '/' ? `${path.replace(/^\/+|\/+$/, '')}/${fileName}` : fileName
|
||||||
}
|
}
|
||||||
|
|
||||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||||
const { fileName, config } = configMap
|
const { fileName, config } = configMap
|
||||||
try {
|
try {
|
||||||
const client = new OSS({ ...config, region: config.area })
|
const client = new OSS({ ...config, region: config.area })
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const apiMap: IStringKeyMap = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class ALLApi {
|
export default class ALLApi {
|
||||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const api = apiMap[configMap.type]
|
const api = apiMap[configMap.type]
|
||||||
return api ? await api.delete(configMap) : false
|
return api ? await api.delete(configMap) : false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { removeFileFromS3InMain } from '~/utils/deleteFunc'
|
|||||||
import { deleteFailedLog } from '~/utils/deleteLog'
|
import { deleteFailedLog } from '~/utils/deleteLog'
|
||||||
|
|
||||||
export default class AwsS3Api {
|
export default class AwsS3Api {
|
||||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
return await removeFileFromS3InMain(getRawData(configMap))
|
return await removeFileFromS3InMain(getRawData(configMap))
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { removeFileFromDogeInMain } from '~/utils/deleteFunc'
|
|||||||
import { deleteFailedLog } from '~/utils/deleteLog'
|
import { deleteFailedLog } from '~/utils/deleteLog'
|
||||||
|
|
||||||
export default class AwsS3Api {
|
export default class AwsS3Api {
|
||||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
return await removeFileFromDogeInMain(getRawData(configMap))
|
return await removeFileFromDogeInMain(getRawData(configMap))
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
|||||||
@@ -10,18 +10,18 @@ interface IConfigMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class GithubApi {
|
export default class GithubApi {
|
||||||
static #createOctokit (token: string) {
|
static #createOctokit(token: string) {
|
||||||
return new Octokit({
|
return new Octokit({
|
||||||
auth: token
|
auth: token
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static #createKey (path: string | undefined, fileName: string): string {
|
static #createKey(path: string | undefined, fileName: string): string {
|
||||||
const formatedFileName = fileName.replace(/%2F/g, '/')
|
const formatedFileName = fileName.replace(/%2F/g, '/')
|
||||||
return path && path !== '/' ? `${path.replace(/^\/+|\/+$/, '')}/${formatedFileName}` : formatedFileName
|
return path && path !== '/' ? `${path.replace(/^\/+|\/+$/, '')}/${formatedFileName}` : formatedFileName
|
||||||
}
|
}
|
||||||
|
|
||||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||||
const {
|
const {
|
||||||
fileName,
|
fileName,
|
||||||
hash,
|
hash,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { removeFileFromHuaweiInMain } from '~/utils/deleteFunc'
|
|||||||
import { deleteFailedLog } from '~/utils/deleteLog'
|
import { deleteFailedLog } from '~/utils/deleteLog'
|
||||||
|
|
||||||
export default class HuaweicloudApi {
|
export default class HuaweicloudApi {
|
||||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
return await removeFileFromHuaweiInMain(getRawData(configMap))
|
return await removeFileFromHuaweiInMain(getRawData(configMap))
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ interface IConfigMap {
|
|||||||
export default class ImgurApi {
|
export default class ImgurApi {
|
||||||
static #baseUrl = 'https://api.imgur.com/3'
|
static #baseUrl = 'https://api.imgur.com/3'
|
||||||
|
|
||||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||||
const { config: { clientId = '', username = '', accessToken = '' } = {}, hash = '' } = configMap
|
const { config: { clientId = '', username = '', accessToken = '' } = {}, hash = '' } = configMap
|
||||||
let Authorization: string, apiUrl: string
|
let Authorization: string, apiUrl: string
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ interface IConfigMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class LocalApi {
|
export default class LocalApi {
|
||||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||||
const { hash } = configMap
|
const { hash } = configMap
|
||||||
if (!hash) {
|
if (!hash) {
|
||||||
deleteLog(hash, 'Local', false, 'Local.delete: invalid params')
|
deleteLog(hash, 'Local', false, 'Local.delete: invalid params')
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type { IStringKeyMap } from '#/types/types'
|
|||||||
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
|
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
|
||||||
|
|
||||||
export default class LskyplistApi {
|
export default class LskyplistApi {
|
||||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { hash, config } = configMap
|
const { hash, config } = configMap
|
||||||
if (!hash || !config || !config.token) {
|
if (!hash || !config || !config.token) {
|
||||||
deleteLog(hash, 'Lskyplist', false, 'LskyplistApi.delete: invalid params')
|
deleteLog(hash, 'Lskyplist', false, 'LskyplistApi.delete: invalid params')
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type { IStringKeyMap } from '#/types/types'
|
|||||||
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
|
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
|
||||||
|
|
||||||
export default class PiclistApi {
|
export default class PiclistApi {
|
||||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { config, fullResult } = configMap
|
const { config, fullResult } = configMap
|
||||||
const { host, port } = config
|
const { host, port } = config
|
||||||
if (!fullResult) return true
|
if (!fullResult) return true
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ interface IConfigMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class QiniuApi {
|
export default class QiniuApi {
|
||||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||||
const {
|
const {
|
||||||
fileName,
|
fileName,
|
||||||
config: { accessKey, secretKey, bucket, path }
|
config: { accessKey, secretKey, bucket, path }
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { removeFileFromSFTPInMain } from '~/utils/deleteFunc'
|
|||||||
import { deleteFailedLog } from '~/utils/deleteLog'
|
import { deleteFailedLog } from '~/utils/deleteLog'
|
||||||
|
|
||||||
export default class SftpPlistApi {
|
export default class SftpPlistApi {
|
||||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { fileName, config } = configMap
|
const { fileName, config } = configMap
|
||||||
try {
|
try {
|
||||||
return await removeFileFromSFTPInMain(getRawData(config), fileName)
|
return await removeFileFromSFTPInMain(getRawData(config), fileName)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ interface IConfigMap {
|
|||||||
export default class SmmsApi {
|
export default class SmmsApi {
|
||||||
static readonly #baseUrl = 'https://smms.app/api/v2'
|
static readonly #baseUrl = 'https://smms.app/api/v2'
|
||||||
|
|
||||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||||
const { hash, config } = configMap
|
const { hash, config } = configMap
|
||||||
if (!hash || !config || !config.token) {
|
if (!hash || !config || !config.token) {
|
||||||
deleteLog(hash, 'Smms', false, 'SmmsApi.delete: invalid params')
|
deleteLog(hash, 'Smms', false, 'SmmsApi.delete: invalid params')
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ interface IConfigMap {
|
|||||||
config: PartialKeys<ITcYunConfig, 'path'>
|
config: PartialKeys<ITcYunConfig, 'path'>
|
||||||
}
|
}
|
||||||
export default class TcyunApi {
|
export default class TcyunApi {
|
||||||
static #createCOS (SecretId: string, SecretKey: string): COS {
|
static #createCOS(SecretId: string, SecretKey: string): COS {
|
||||||
return new COS({
|
return new COS({
|
||||||
SecretId,
|
SecretId,
|
||||||
SecretKey
|
SecretKey
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||||
const {
|
const {
|
||||||
fileName,
|
fileName,
|
||||||
config: { secretId, secretKey, bucket, area, path }
|
config: { secretId, secretKey, bucket, area, path }
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ interface IConfigMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class UpyunApi {
|
export default class UpyunApi {
|
||||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||||
const {
|
const {
|
||||||
fileName,
|
fileName,
|
||||||
config: { bucket, operator, password, path }
|
config: { bucket, operator, password, path }
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ interface IConfigMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class WebdavApi {
|
export default class WebdavApi {
|
||||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
static async delete(configMap: IConfigMap): Promise<boolean> {
|
||||||
const {
|
const {
|
||||||
fileName,
|
fileName,
|
||||||
config: { host, username, password, path, sslEnabled, authType }
|
config: { host, username, password, path, sslEnabled, authType }
|
||||||
|
|||||||
@@ -8,7 +8,16 @@ import { BrowserWindow, dialog, ipcMain, IpcMainEvent, MessageBoxOptions, Notifi
|
|||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import { cloneDeep } from 'lodash-es'
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
|
||||||
import type { IGuiApi, ImgInfo, IShowFileExplorerOption, IShowInputBoxOption, IShowMessageBoxOption, IShowMessageBoxResult, IShowNotificationOption, IUploadOption } from '#/types/types'
|
import type {
|
||||||
|
IGuiApi,
|
||||||
|
ImgInfo,
|
||||||
|
IShowFileExplorerOption,
|
||||||
|
IShowInputBoxOption,
|
||||||
|
IShowMessageBoxOption,
|
||||||
|
IShowMessageBoxResult,
|
||||||
|
IShowNotificationOption,
|
||||||
|
IUploadOption
|
||||||
|
} from '#/types/types'
|
||||||
import { SHOW_INPUT_BOX } from '~/events/constant'
|
import { SHOW_INPUT_BOX } from '~/events/constant'
|
||||||
import { T as $t } from '~/i18n'
|
import { T as $t } from '~/i18n'
|
||||||
import { handleCopyUrl } from '~/utils/common'
|
import { handleCopyUrl } from '~/utils/common'
|
||||||
@@ -21,18 +30,18 @@ class GuiApi implements IGuiApi {
|
|||||||
private static instance: GuiApi
|
private static instance: GuiApi
|
||||||
private windowId: number = -1
|
private windowId: number = -1
|
||||||
private settingWindowId: number = -1
|
private settingWindowId: number = -1
|
||||||
private constructor () {
|
private constructor() {
|
||||||
console.log('init guiapi')
|
console.log('init guiapi')
|
||||||
}
|
}
|
||||||
|
|
||||||
static getInstance (): GuiApi {
|
static getInstance(): GuiApi {
|
||||||
if (!GuiApi.instance) {
|
if (!GuiApi.instance) {
|
||||||
GuiApi.instance = new GuiApi()
|
GuiApi.instance = new GuiApi()
|
||||||
}
|
}
|
||||||
return GuiApi.instance
|
return GuiApi.instance
|
||||||
}
|
}
|
||||||
|
|
||||||
private async showSettingWindow () {
|
private async showSettingWindow() {
|
||||||
this.settingWindowId = await getSettingWindowId()
|
this.settingWindowId = await getSettingWindowId()
|
||||||
const settingWindow = BrowserWindow.fromId(this.settingWindowId)
|
const settingWindow = BrowserWindow.fromId(this.settingWindowId)
|
||||||
if (settingWindow?.isVisible()) {
|
if (settingWindow?.isVisible()) {
|
||||||
@@ -46,11 +55,11 @@ class GuiApi implements IGuiApi {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private getWebcontentsByWindowId (id: number) {
|
private getWebcontentsByWindowId(id: number) {
|
||||||
return BrowserWindow.fromId(id)?.webContents
|
return BrowserWindow.fromId(id)?.webContents
|
||||||
}
|
}
|
||||||
|
|
||||||
async showInputBox (
|
async showInputBox(
|
||||||
options: IShowInputBoxOption = {
|
options: IShowInputBoxOption = {
|
||||||
title: '',
|
title: '',
|
||||||
placeholder: ''
|
placeholder: ''
|
||||||
@@ -65,13 +74,13 @@ class GuiApi implements IGuiApi {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async showFileExplorer (options: IShowFileExplorerOption = {}) {
|
async showFileExplorer(options: IShowFileExplorerOption = {}) {
|
||||||
this.windowId = await getWindowId()
|
this.windowId = await getWindowId()
|
||||||
const res = await dialog.showOpenDialog(BrowserWindow.fromId(this.windowId)!, options)
|
const res = await dialog.showOpenDialog(BrowserWindow.fromId(this.windowId)!, options)
|
||||||
return res.filePaths || []
|
return res.filePaths || []
|
||||||
}
|
}
|
||||||
|
|
||||||
async upload (input: IUploadOption) {
|
async upload(input: IUploadOption) {
|
||||||
this.windowId = await getWindowId()
|
this.windowId = await getWindowId()
|
||||||
const webContents = this.getWebcontentsByWindowId(this.windowId)
|
const webContents = this.getWebcontentsByWindowId(this.windowId)
|
||||||
const rawInput = cloneDeep(input)
|
const rawInput = cloneDeep(input)
|
||||||
@@ -122,7 +131,7 @@ class GuiApi implements IGuiApi {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
showNotification (
|
showNotification(
|
||||||
options: IShowNotificationOption = {
|
options: IShowNotificationOption = {
|
||||||
title: '',
|
title: '',
|
||||||
body: ''
|
body: ''
|
||||||
@@ -135,7 +144,7 @@ class GuiApi implements IGuiApi {
|
|||||||
notification.show()
|
notification.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
showMessageBox (
|
showMessageBox(
|
||||||
options: IShowMessageBoxOption = {
|
options: IShowMessageBoxOption = {
|
||||||
title: '',
|
title: '',
|
||||||
message: '',
|
message: '',
|
||||||
@@ -159,7 +168,7 @@ class GuiApi implements IGuiApi {
|
|||||||
/**
|
/**
|
||||||
* get picgo config/data path
|
* get picgo config/data path
|
||||||
*/
|
*/
|
||||||
async getConfigPath () {
|
async getConfigPath() {
|
||||||
const currentConfigPath = dbPathChecker()
|
const currentConfigPath = dbPathChecker()
|
||||||
const galleryDBPath = getGalleryDBPath().dbPath
|
const galleryDBPath = getGalleryDBPath().dbPath
|
||||||
return {
|
return {
|
||||||
@@ -169,12 +178,12 @@ class GuiApi implements IGuiApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get galleryDB (): DBStore {
|
get galleryDB(): DBStore {
|
||||||
return new Proxy<DBStore>(GalleryDB.getInstance(), {
|
return new Proxy<DBStore>(GalleryDB.getInstance(), {
|
||||||
get (target, prop: keyof DBStore) {
|
get(target, prop: keyof DBStore) {
|
||||||
if (prop === 'overwrite') {
|
if (prop === 'overwrite') {
|
||||||
return new Proxy(GalleryDB.getInstance().overwrite, {
|
return new Proxy(GalleryDB.getInstance().overwrite, {
|
||||||
apply (target, ctx, args) {
|
apply(target, ctx, args) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const guiApi = GuiApi.getInstance()
|
const guiApi = GuiApi.getInstance()
|
||||||
guiApi
|
guiApi
|
||||||
@@ -197,7 +206,7 @@ class GuiApi implements IGuiApi {
|
|||||||
}
|
}
|
||||||
if (prop === 'removeById') {
|
if (prop === 'removeById') {
|
||||||
return new Proxy(GalleryDB.getInstance().removeById, {
|
return new Proxy(GalleryDB.getInstance().removeById, {
|
||||||
apply (target, ctx, args) {
|
apply(target, ctx, args) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const guiApi = GuiApi.getInstance()
|
const guiApi = GuiApi.getInstance()
|
||||||
guiApi
|
guiApi
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import windowManager from 'apis/app/window/windowManager'
|
|||||||
import type { IFileWithPath } from '#/types/types'
|
import type { IFileWithPath } from '#/types/types'
|
||||||
import { IWindowList } from '~/utils/enum'
|
import { IWindowList } from '~/utils/enum'
|
||||||
|
|
||||||
function initEventCenter () {
|
function initEventCenter() {
|
||||||
const eventList: any = {
|
const eventList: any = {
|
||||||
'picgo:upload': uploadClipboardFiles,
|
'picgo:upload': uploadClipboardFiles,
|
||||||
[UPLOAD_WITH_CLIPBOARD_FILES]: busCallUploadClipboardFiles,
|
[UPLOAD_WITH_CLIPBOARD_FILES]: busCallUploadClipboardFiles,
|
||||||
@@ -31,31 +31,31 @@ function initEventCenter () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function busCallUploadClipboardFiles () {
|
async function busCallUploadClipboardFiles() {
|
||||||
const result = await uploadClipboardFiles()
|
const result = await uploadClipboardFiles()
|
||||||
const imgUrl = result.url
|
const imgUrl = result.url
|
||||||
bus.emit(UPLOAD_WITH_CLIPBOARD_FILES_RESPONSE, imgUrl)
|
bus.emit(UPLOAD_WITH_CLIPBOARD_FILES_RESPONSE, imgUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function busCallUploadFiles (pathList: IFileWithPath[]) {
|
async function busCallUploadFiles(pathList: IFileWithPath[]) {
|
||||||
const win = windowManager.getAvailableWindow()
|
const win = windowManager.getAvailableWindow()
|
||||||
const result = await uploadChoosedFiles(win.webContents, pathList)
|
const result = await uploadChoosedFiles(win.webContents, pathList)
|
||||||
const urls = result.map((item: any) => item.url)
|
const urls = result.map((item: any) => item.url)
|
||||||
bus.emit(UPLOAD_WITH_FILES_RESPONSE, urls)
|
bus.emit(UPLOAD_WITH_FILES_RESPONSE, urls)
|
||||||
}
|
}
|
||||||
|
|
||||||
function busCallGetWindowId () {
|
function busCallGetWindowId() {
|
||||||
const win = windowManager.getAvailableWindow()
|
const win = windowManager.getAvailableWindow()
|
||||||
bus.emit(GET_WINDOW_ID_REPONSE, win.id)
|
bus.emit(GET_WINDOW_ID_REPONSE, win.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
function busCallGetSettingWindowId () {
|
function busCallGetSettingWindowId() {
|
||||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
bus.emit(GET_SETTING_WINDOW_ID_RESPONSE, settingWindow.id)
|
bus.emit(GET_SETTING_WINDOW_ID_RESPONSE, settingWindow.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
listen () {
|
listen() {
|
||||||
initEventCenter()
|
initEventCenter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
export const SHOW_INPUT_BOX = 'SHOW_INPUT_BOX'
|
export const SHOW_INPUT_BOX = 'SHOW_INPUT_BOX'
|
||||||
export const SHOW_INPUT_BOX_RESPONSE = 'SHOW_INPUT_BOX_RESPONSE'
|
export const SHOW_INPUT_BOX_RESPONSE = 'SHOW_INPUT_BOX_RESPONSE'
|
||||||
export const TOGGLE_SHORTKEY_MODIFIED_MODE = 'TOGGLE_SHORTKEY_MODIFIED_MODE'
|
export const TOGGLE_SHORTKEY_MODIFIED_MODE = 'TOGGLE_SHORTKEY_MODIFIED_MODE'
|
||||||
// picgo plugin
|
// picgo plugin
|
||||||
export const PICGO_CONFIG_PLUGIN = 'PICGO_CONFIG_PLUGIN'
|
export const PICGO_CONFIG_PLUGIN = 'PICGO_CONFIG_PLUGIN'
|
||||||
export const PICGO_HANDLE_PLUGIN_ING = 'PICGO_HANDLE_PLUGIN_ING'
|
export const PICGO_HANDLE_PLUGIN_ING = 'PICGO_HANDLE_PLUGIN_ING'
|
||||||
export const PICGO_HANDLE_PLUGIN_DONE = 'PICGO_HANDLE_PLUGIN_DONE'
|
export const PICGO_HANDLE_PLUGIN_DONE = 'PICGO_HANDLE_PLUGIN_DONE'
|
||||||
export const PICGO_TOGGLE_PLUGIN = 'PICGO_TOGGLE_PLUGIN'
|
export const PICGO_TOGGLE_PLUGIN = 'PICGO_TOGGLE_PLUGIN'
|
||||||
// picgo uploader
|
// picgo uploader
|
||||||
export const RENAME_FILE_NAME = 'RENAME_FILE_NAME'
|
export const RENAME_FILE_NAME = 'RENAME_FILE_NAME'
|
||||||
export const GET_RENAME_FILE_NAME = 'GET_RENAME_FILE_NAME'
|
export const GET_RENAME_FILE_NAME = 'GET_RENAME_FILE_NAME'
|
||||||
export const SHOW_MAIN_PAGE_QRCODE = 'SHOW_MAIN_PAGE_QRCODE'
|
export const SHOW_MAIN_PAGE_QRCODE = 'SHOW_MAIN_PAGE_QRCODE'
|
||||||
// rpc
|
// rpc
|
||||||
export const RPC_ACTIONS = 'RPC_ACTIONS'
|
export const RPC_ACTIONS = 'RPC_ACTIONS'
|
||||||
export const RPC_ACTIONS_INVOKE = 'RPC_ACTIONS_INVOKE'
|
export const RPC_ACTIONS_INVOKE = 'RPC_ACTIONS_INVOKE'
|
||||||
|
|||||||
@@ -46,19 +46,19 @@ const buildMiniPageMenu = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('UPLOAD_BY_CLIPBOARD'),
|
label: $t('UPLOAD_BY_CLIPBOARD'),
|
||||||
click () {
|
click() {
|
||||||
uploadClipboardFiles()
|
uploadClipboardFiles()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('HIDE_MINI_WINDOW'),
|
label: $t('HIDE_MINI_WINDOW'),
|
||||||
click () {
|
click() {
|
||||||
BrowserWindow.getFocusedWindow()!.hide()
|
BrowserWindow.getFocusedWindow()!.hide()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('START_WATCH_CLIPBOARD'),
|
label: $t('START_WATCH_CLIPBOARD'),
|
||||||
click () {
|
click() {
|
||||||
db.set(configPaths.settings.isListeningClipboard, true)
|
db.set(configPaths.settings.isListeningClipboard, true)
|
||||||
ClipboardWatcher.startListening()
|
ClipboardWatcher.startListening()
|
||||||
ClipboardWatcher.on('change', () => {
|
ClipboardWatcher.on('change', () => {
|
||||||
@@ -71,7 +71,7 @@ const buildMiniPageMenu = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('STOP_WATCH_CLIPBOARD'),
|
label: $t('STOP_WATCH_CLIPBOARD'),
|
||||||
click () {
|
click() {
|
||||||
db.set(configPaths.settings.isListeningClipboard, false)
|
db.set(configPaths.settings.isListeningClipboard, false)
|
||||||
ClipboardWatcher.stopListening()
|
ClipboardWatcher.stopListening()
|
||||||
ClipboardWatcher.removeAllListeners()
|
ClipboardWatcher.removeAllListeners()
|
||||||
@@ -81,7 +81,7 @@ const buildMiniPageMenu = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('RELOAD_APP'),
|
label: $t('RELOAD_APP'),
|
||||||
click () {
|
click() {
|
||||||
app.relaunch()
|
app.relaunch()
|
||||||
app.exit(0)
|
app.exit(0)
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ const buildMainPageMenu = (win: BrowserWindow) => {
|
|||||||
const template = [
|
const template = [
|
||||||
{
|
{
|
||||||
label: $t('ABOUT'),
|
label: $t('ABOUT'),
|
||||||
click () {
|
click() {
|
||||||
dialog.showMessageBox({
|
dialog.showMessageBox({
|
||||||
title: 'PicList',
|
title: 'PicList',
|
||||||
message: 'PicList',
|
message: 'PicList',
|
||||||
@@ -108,26 +108,26 @@ const buildMainPageMenu = (win: BrowserWindow) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('SHOW_PICBED_QRCODE'),
|
label: $t('SHOW_PICBED_QRCODE'),
|
||||||
click () {
|
click() {
|
||||||
win?.webContents?.send(SHOW_MAIN_PAGE_QRCODE)
|
win?.webContents?.send(SHOW_MAIN_PAGE_QRCODE)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('OPEN_TOOLBOX'),
|
label: $t('OPEN_TOOLBOX'),
|
||||||
click () {
|
click() {
|
||||||
const window = windowManager.create(IWindowList.TOOLBOX_WINDOW)
|
const window = windowManager.create(IWindowList.TOOLBOX_WINDOW)
|
||||||
window?.show()
|
window?.show()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('SHOW_DEVTOOLS'),
|
label: $t('SHOW_DEVTOOLS'),
|
||||||
click () {
|
click() {
|
||||||
win?.webContents?.openDevTools({ mode: 'detach' })
|
win?.webContents?.openDevTools({ mode: 'detach' })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('FEEDBACK'),
|
label: $t('FEEDBACK'),
|
||||||
click () {
|
click() {
|
||||||
const url = 'https://github.com/Kuingsmile/PicList/issues'
|
const url = 'https://github.com/Kuingsmile/PicList/issues'
|
||||||
shell.openExternal(url)
|
shell.openExternal(url)
|
||||||
}
|
}
|
||||||
@@ -176,10 +176,10 @@ const buildSecondPicBedMenu = () => {
|
|||||||
: undefined,
|
: undefined,
|
||||||
click: !hasSubmenu
|
click: !hasSubmenu
|
||||||
? function () {
|
? function () {
|
||||||
picgo.saveConfig({
|
picgo.saveConfig({
|
||||||
[configPaths.picBed.secondUploader]: item.type
|
[configPaths.picBed.secondUploader]: item.type
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -233,15 +233,15 @@ const buildPicBedListMenu = () => {
|
|||||||
: undefined,
|
: undefined,
|
||||||
click: !hasSubmenu
|
click: !hasSubmenu
|
||||||
? function () {
|
? function () {
|
||||||
picgo.saveConfig({
|
picgo.saveConfig({
|
||||||
[configPaths.picBed.current]: item.type,
|
[configPaths.picBed.current]: item.type,
|
||||||
[configPaths.picBed.uploader]: item.type
|
[configPaths.picBed.uploader]: item.type
|
||||||
})
|
})
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
|
windowManager.get(IWindowList.SETTING_WINDOW)!.webContents.send('syncPicBed')
|
||||||
|
}
|
||||||
|
setTrayToolTip(item.type)
|
||||||
}
|
}
|
||||||
setTrayToolTip(item.type)
|
|
||||||
}
|
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -278,7 +278,7 @@ const buildPluginPageMenu = (plugin: IPicGoPlugin) => {
|
|||||||
{
|
{
|
||||||
label: $t('ENABLE_PLUGIN'),
|
label: $t('ENABLE_PLUGIN'),
|
||||||
enabled: !plugin.enabled,
|
enabled: !plugin.enabled,
|
||||||
click () {
|
click() {
|
||||||
picgo.saveConfig({
|
picgo.saveConfig({
|
||||||
[`picgoPlugins.${plugin.fullName}`]: true
|
[`picgoPlugins.${plugin.fullName}`]: true
|
||||||
})
|
})
|
||||||
@@ -289,7 +289,7 @@ const buildPluginPageMenu = (plugin: IPicGoPlugin) => {
|
|||||||
{
|
{
|
||||||
label: $t('DISABLE_PLUGIN'),
|
label: $t('DISABLE_PLUGIN'),
|
||||||
enabled: plugin.enabled,
|
enabled: plugin.enabled,
|
||||||
click () {
|
click() {
|
||||||
picgo.saveConfig({
|
picgo.saveConfig({
|
||||||
[`picgoPlugins.${plugin.fullName}`]: false
|
[`picgoPlugins.${plugin.fullName}`]: false
|
||||||
})
|
})
|
||||||
@@ -307,7 +307,7 @@ const buildPluginPageMenu = (plugin: IPicGoPlugin) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('UNINSTALL_PLUGIN'),
|
label: $t('UNINSTALL_PLUGIN'),
|
||||||
click () {
|
click() {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
window.webContents.send(PICGO_HANDLE_PLUGIN_ING, plugin.fullName)
|
window.webContents.send(PICGO_HANDLE_PLUGIN_ING, plugin.fullName)
|
||||||
handlePluginUninstall(plugin.fullName)
|
handlePluginUninstall(plugin.fullName)
|
||||||
@@ -315,7 +315,7 @@ const buildPluginPageMenu = (plugin: IPicGoPlugin) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('UPDATE_PLUGIN'),
|
label: $t('UPDATE_PLUGIN'),
|
||||||
click () {
|
click() {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
window.webContents.send(PICGO_HANDLE_PLUGIN_ING, plugin.fullName)
|
window.webContents.send(PICGO_HANDLE_PLUGIN_ING, plugin.fullName)
|
||||||
handlePluginUpdate(plugin.fullName)
|
handlePluginUpdate(plugin.fullName)
|
||||||
@@ -328,7 +328,7 @@ const buildPluginPageMenu = (plugin: IPicGoPlugin) => {
|
|||||||
label: $t('CONFIG_THING', {
|
label: $t('CONFIG_THING', {
|
||||||
c: `${i} - ${plugin.config[i].fullName || plugin.config[i].name}`
|
c: `${i} - ${plugin.config[i].fullName || plugin.config[i].name}`
|
||||||
}),
|
}),
|
||||||
click () {
|
click() {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const currentType = i
|
const currentType = i
|
||||||
const configName = plugin.config[i].fullName || plugin.config[i].name
|
const configName = plugin.config[i].fullName || plugin.config[i].name
|
||||||
@@ -346,7 +346,7 @@ const buildPluginPageMenu = (plugin: IPicGoPlugin) => {
|
|||||||
const pluginTransformer = plugin.config.transformer.name
|
const pluginTransformer = plugin.config.transformer.name
|
||||||
const obj = {
|
const obj = {
|
||||||
label: `${currentTransformer === pluginTransformer ? $t('DISABLE') : $t('ENABLE')}transformer - ${plugin.config.transformer.name}`,
|
label: `${currentTransformer === pluginTransformer ? $t('DISABLE') : $t('ENABLE')}transformer - ${plugin.config.transformer.name}`,
|
||||||
click () {
|
click() {
|
||||||
const transformer = plugin.config.transformer.name
|
const transformer = plugin.config.transformer.name
|
||||||
const currentTransformer = picgo.getConfig<string>(configPaths.picBed.transformer) || 'path'
|
const currentTransformer = picgo.getConfig<string>(configPaths.picBed.transformer) || 'path'
|
||||||
if (currentTransformer === transformer) {
|
if (currentTransformer === transformer) {
|
||||||
@@ -371,7 +371,7 @@ const buildPluginPageMenu = (plugin: IPicGoPlugin) => {
|
|||||||
for (const i of plugin.guiMenu) {
|
for (const i of plugin.guiMenu) {
|
||||||
menu.push({
|
menu.push({
|
||||||
label: i.label,
|
label: i.label,
|
||||||
async click () {
|
async click() {
|
||||||
const picgPlugin = await picgo.pluginLoader.getPlugin(plugin.fullName)
|
const picgPlugin = await picgo.pluginLoader.getPlugin(plugin.fullName)
|
||||||
if (picgPlugin?.guiMenu?.(picgo)?.length) {
|
if (picgPlugin?.guiMenu?.(picgo)?.length) {
|
||||||
const menu: GuiMenuItem[] = picgPlugin.guiMenu(picgo)
|
const menu: GuiMenuItem[] = picgPlugin.guiMenu(picgo)
|
||||||
|
|||||||
@@ -37,12 +37,12 @@ class RPCServer implements IRPCServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
start () {
|
start() {
|
||||||
ipcMain.on(RPC_ACTIONS, this.rpcEventHandler)
|
ipcMain.on(RPC_ACTIONS, this.rpcEventHandler)
|
||||||
ipcMain.handle(RPC_ACTIONS_INVOKE, this.rpcEventHandlerWithResponse)
|
ipcMain.handle(RPC_ACTIONS_INVOKE, this.rpcEventHandlerWithResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
use (routes: IRPCRoutes) {
|
use(routes: IRPCRoutes) {
|
||||||
for (const [action, route] of routes) {
|
for (const [action, route] of routes) {
|
||||||
if (route.type === IRPCType.SEND) {
|
if (route.type === IRPCType.SEND) {
|
||||||
this.routes.set(action, route)
|
this.routes.set(action, route)
|
||||||
@@ -52,7 +52,7 @@ class RPCServer implements IRPCServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stop () {
|
stop() {
|
||||||
ipcMain.off(RPC_ACTIONS, this.rpcEventHandler)
|
ipcMain.off(RPC_ACTIONS, this.rpcEventHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export class RPCRouter implements IRPCRouter {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
routes () {
|
routes() {
|
||||||
return this.routeMap
|
return this.routeMap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import ALLApi from 'apis/delete/allApi'
|
import ALLApi from 'apis/delete/allApi'
|
||||||
|
|
||||||
import type { IIPCEvent } from '#/types/rpc'
|
import type { IIPCEvent } from '#/types/rpc'
|
||||||
import type { ImgInfo } from '#/types/types'
|
import type { ImgInfo } from '#/types/types'
|
||||||
import { IRPCActionType, IRPCType } from '~/utils/enum'
|
import { IRPCActionType, IRPCType } from '~/utils/enum'
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
action: IRPCActionType.DELETE_ALL_API,
|
action: IRPCActionType.DELETE_ALL_API,
|
||||||
handler: async (_: IIPCEvent, args:[item: ImgInfo]) => {
|
handler: async (_: IIPCEvent, args: [item: ImgInfo]) => {
|
||||||
return await ALLApi.delete(args[0])
|
return await ALLApi.delete(args[0])
|
||||||
},
|
},
|
||||||
type: IRPCType.INVOKE
|
type: IRPCType.INVOKE
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -85,11 +85,15 @@ const getPluginList = async (): Promise<IPicGoPlugin[]> => {
|
|||||||
},
|
},
|
||||||
uploader: {
|
uploader: {
|
||||||
name: uploaderName,
|
name: uploaderName,
|
||||||
config: handleConfigWithFunction(getConfig(uploaderName, IPicGoHelperType.uploader as keyof typeof IPicGoHelperType, picgo))
|
config: handleConfigWithFunction(
|
||||||
|
getConfig(uploaderName, IPicGoHelperType.uploader as keyof typeof IPicGoHelperType, picgo)
|
||||||
|
)
|
||||||
},
|
},
|
||||||
transformer: {
|
transformer: {
|
||||||
name: transformerName,
|
name: transformerName,
|
||||||
config: handleConfigWithFunction(getConfig(uploaderName, IPicGoHelperType.transformer as keyof typeof IPicGoHelperType, picgo))
|
config: handleConfigWithFunction(
|
||||||
|
getConfig(uploaderName, IPicGoHelperType.transformer as keyof typeof IPicGoHelperType, picgo)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
enabled: picgo.getConfig(`picgoPlugins.${pluginList[i]}`),
|
enabled: picgo.getConfig(`picgoPlugins.${pluginList[i]}`),
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ import { sendToolboxResWithType } from '~/events/rpc/routes/toolbox/utils'
|
|||||||
import { T as $t } from '~/i18n'
|
import { T as $t } from '~/i18n'
|
||||||
import { IToolboxItemCheckStatus, IToolboxItemType } from '~/utils/enum'
|
import { IToolboxItemCheckStatus, IToolboxItemType } from '~/utils/enum'
|
||||||
|
|
||||||
export const checkFileMap: IToolboxCheckerMap<
|
export const checkFileMap: IToolboxCheckerMap<string> = {
|
||||||
string
|
|
||||||
> = {
|
|
||||||
[IToolboxItemType.IS_CONFIG_FILE_BROKEN]: async (event: IpcMainEvent) => {
|
[IToolboxItemType.IS_CONFIG_FILE_BROKEN]: async (event: IpcMainEvent) => {
|
||||||
const sendToolboxRes = sendToolboxResWithType(IToolboxItemType.IS_CONFIG_FILE_BROKEN)
|
const sendToolboxRes = sendToolboxResWithType(IToolboxItemType.IS_CONFIG_FILE_BROKEN)
|
||||||
sendToolboxRes(event, {
|
sendToolboxRes(event, {
|
||||||
@@ -62,9 +60,7 @@ export const checkFileMap: IToolboxCheckerMap<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fixFileMap: IToolboxFixMap<
|
export const fixFileMap: IToolboxFixMap<string> = {
|
||||||
string
|
|
||||||
> = {
|
|
||||||
[IToolboxItemType.IS_CONFIG_FILE_BROKEN]: async () => {
|
[IToolboxItemType.IS_CONFIG_FILE_BROKEN]: async () => {
|
||||||
try {
|
try {
|
||||||
fs.unlinkSync(dbPathChecker())
|
fs.unlinkSync(dbPathChecker())
|
||||||
|
|||||||
@@ -1,89 +1,89 @@
|
|||||||
import { dbPathChecker } from '@core/datastore/dbChecker'
|
import { dbPathChecker } from '@core/datastore/dbChecker'
|
||||||
import axios, { AxiosRequestConfig } from 'axios'
|
import axios, { AxiosRequestConfig } from 'axios'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import { IConfig } from 'piclist'
|
import { IConfig } from 'piclist'
|
||||||
import tunnel from 'tunnel'
|
import tunnel from 'tunnel'
|
||||||
|
|
||||||
import type { IToolboxCheckerMap } from '#/types/rpc'
|
import type { IToolboxCheckerMap } from '#/types/rpc'
|
||||||
import { sendToolboxResWithType } from '~/events/rpc/routes/toolbox/utils'
|
import { sendToolboxResWithType } from '~/events/rpc/routes/toolbox/utils'
|
||||||
import { T as $t } from '~/i18n'
|
import { T as $t } from '~/i18n'
|
||||||
import { IToolboxItemCheckStatus, IToolboxItemType } from '~/utils/enum'
|
import { IToolboxItemCheckStatus, IToolboxItemType } from '~/utils/enum'
|
||||||
|
|
||||||
function getProxy (proxyStr: string): AxiosRequestConfig['proxy'] | null {
|
function getProxy(proxyStr: string): AxiosRequestConfig['proxy'] | null {
|
||||||
if (proxyStr) {
|
if (proxyStr) {
|
||||||
try {
|
try {
|
||||||
const proxyOptions = new URL(proxyStr)
|
const proxyOptions = new URL(proxyStr)
|
||||||
return {
|
return {
|
||||||
host: proxyOptions.hostname,
|
host: proxyOptions.hostname,
|
||||||
port: parseInt(proxyOptions.port || '0', 10),
|
port: parseInt(proxyOptions.port || '0', 10),
|
||||||
protocol: proxyOptions.protocol
|
protocol: proxyOptions.protocol
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendToolboxRes = sendToolboxResWithType(IToolboxItemType.HAS_PROBLEM_WITH_PROXY)
|
const sendToolboxRes = sendToolboxResWithType(IToolboxItemType.HAS_PROBLEM_WITH_PROXY)
|
||||||
|
|
||||||
export const checkProxyMap: IToolboxCheckerMap<string> = {
|
export const checkProxyMap: IToolboxCheckerMap<string> = {
|
||||||
[IToolboxItemType.HAS_PROBLEM_WITH_PROXY]: async event => {
|
[IToolboxItemType.HAS_PROBLEM_WITH_PROXY]: async event => {
|
||||||
sendToolboxRes(event, {
|
sendToolboxRes(event, {
|
||||||
status: IToolboxItemCheckStatus.LOADING
|
status: IToolboxItemCheckStatus.LOADING
|
||||||
})
|
})
|
||||||
const configFilePath = dbPathChecker()
|
const configFilePath = dbPathChecker()
|
||||||
if (fs.existsSync(configFilePath)) {
|
if (fs.existsSync(configFilePath)) {
|
||||||
let config: IConfig | undefined
|
let config: IConfig | undefined
|
||||||
try {
|
try {
|
||||||
config = (await fs.readJSON(configFilePath)) as IConfig
|
config = (await fs.readJSON(configFilePath)) as IConfig
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return sendToolboxRes(event, {
|
return sendToolboxRes(event, {
|
||||||
status: IToolboxItemCheckStatus.SUCCESS,
|
status: IToolboxItemCheckStatus.SUCCESS,
|
||||||
msg: $t('TOOLBOX_CHECK_PROXY_NO_PROXY_TIPS')
|
msg: $t('TOOLBOX_CHECK_PROXY_NO_PROXY_TIPS')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const proxy = config.picBed?.proxy
|
const proxy = config.picBed?.proxy
|
||||||
if (!proxy) {
|
if (!proxy) {
|
||||||
return sendToolboxRes(event, {
|
return sendToolboxRes(event, {
|
||||||
status: IToolboxItemCheckStatus.SUCCESS,
|
status: IToolboxItemCheckStatus.SUCCESS,
|
||||||
msg: $t('TOOLBOX_CHECK_PROXY_NO_PROXY_TIPS')
|
msg: $t('TOOLBOX_CHECK_PROXY_NO_PROXY_TIPS')
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
const proxyOptions = getProxy(proxy)
|
const proxyOptions = getProxy(proxy)
|
||||||
if (!proxyOptions) {
|
if (!proxyOptions) {
|
||||||
return sendToolboxRes(event, {
|
return sendToolboxRes(event, {
|
||||||
status: IToolboxItemCheckStatus.ERROR,
|
status: IToolboxItemCheckStatus.ERROR,
|
||||||
msg: $t('TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_CORRECT')
|
msg: $t('TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_CORRECT')
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
const httpsAgent = tunnel.httpsOverHttp({
|
const httpsAgent = tunnel.httpsOverHttp({
|
||||||
proxy: {
|
proxy: {
|
||||||
host: proxyOptions.host,
|
host: proxyOptions.host,
|
||||||
port: proxyOptions.port
|
port: proxyOptions.port
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
await axios.get('https://www.google.com', {
|
await axios.get('https://www.google.com', {
|
||||||
httpsAgent
|
httpsAgent
|
||||||
})
|
})
|
||||||
return sendToolboxRes(event, {
|
return sendToolboxRes(event, {
|
||||||
status: IToolboxItemCheckStatus.SUCCESS,
|
status: IToolboxItemCheckStatus.SUCCESS,
|
||||||
msg: $t('TOOLBOX_CHECK_PROXY_SUCCESS_TIPS')
|
msg: $t('TOOLBOX_CHECK_PROXY_SUCCESS_TIPS')
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return sendToolboxRes(event, {
|
return sendToolboxRes(event, {
|
||||||
status: IToolboxItemCheckStatus.ERROR,
|
status: IToolboxItemCheckStatus.ERROR,
|
||||||
msg: $t('TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_WORKING')
|
msg: $t('TOOLBOX_CHECK_PROXY_PROXY_IS_NOT_WORKING')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sendToolboxRes(event, {
|
sendToolboxRes(event, {
|
||||||
status: IToolboxItemCheckStatus.SUCCESS,
|
status: IToolboxItemCheckStatus.SUCCESS,
|
||||||
msg: $t('TOOLBOX_CHECK_PROXY_NO_PROXY_TIPS')
|
msg: $t('TOOLBOX_CHECK_PROXY_NO_PROXY_TIPS')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { IpcMainEvent } from 'electron'
|
|||||||
import type { IToolboxCheckRes } from '#/types/rpc'
|
import type { IToolboxCheckRes } from '#/types/rpc'
|
||||||
import { IRPCActionType } from '~/utils/enum'
|
import { IRPCActionType } from '~/utils/enum'
|
||||||
|
|
||||||
export function sendToolboxResWithType (type: string) {
|
export function sendToolboxResWithType(type: string) {
|
||||||
return (event: IpcMainEvent, res?: Omit<IToolboxCheckRes, 'type'>) => {
|
return (event: IpcMainEvent, res?: Omit<IToolboxCheckRes, 'type'>) => {
|
||||||
return event.sender.send(IRPCActionType.TOOLBOX_CHECK_RES, {
|
return event.sender.send(IRPCActionType.TOOLBOX_CHECK_RES, {
|
||||||
...res,
|
...res,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const serverPort = 36699
|
|||||||
|
|
||||||
let server: http.Server
|
let server: http.Server
|
||||||
|
|
||||||
export function startFileServer () {
|
export function startFileServer() {
|
||||||
server = http.createServer((req, res) => {
|
server = http.createServer((req, res) => {
|
||||||
const requestPath = req.url?.split('?')[0]
|
const requestPath = req.url?.split('?')[0]
|
||||||
const filePath = path.join(imgFilePath, decodeURIComponent(requestPath as string))
|
const filePath = path.join(imgFilePath, decodeURIComponent(requestPath as string))
|
||||||
@@ -36,7 +36,7 @@ export function startFileServer () {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stopFileServer () {
|
export function stopFileServer() {
|
||||||
server.close(() => {
|
server.close(() => {
|
||||||
logger.info('File server is stopped')
|
logger.info('File server is stopped')
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -33,18 +33,18 @@ class I18nManager {
|
|||||||
readonly defaultLanguage: string = 'zh-CN'
|
readonly defaultLanguage: string = 'zh-CN'
|
||||||
private i18nFileList: II18nItem[] = builtinI18nList
|
private i18nFileList: II18nItem[] = builtinI18nList
|
||||||
|
|
||||||
setOutterI18nFolder (folder: string) {
|
setOutterI18nFolder(folder: string) {
|
||||||
this.outterI18nFolder = folder
|
this.outterI18nFolder = folder
|
||||||
}
|
}
|
||||||
|
|
||||||
addI18nFile (file: string, label: string) {
|
addI18nFile(file: string, label: string) {
|
||||||
this.i18nFileList.push({
|
this.i18nFileList.push({
|
||||||
label,
|
label,
|
||||||
value: file
|
value: file
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private getLocales (lang: string): ILocales {
|
private getLocales(lang: string): ILocales {
|
||||||
if (this.localesMap.has(lang)) {
|
if (this.localesMap.has(lang)) {
|
||||||
return this.localesMap.get(lang)!
|
return this.localesMap.get(lang)!
|
||||||
}
|
}
|
||||||
@@ -71,13 +71,13 @@ class I18nManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setCurrentLanguage (lang: string) {
|
setCurrentLanguage(lang: string) {
|
||||||
const locales = this.getLocales(lang)
|
const locales = this.getLocales(lang)
|
||||||
this.currentLanguage = lang
|
this.currentLanguage = lang
|
||||||
this.initI18n(lang, locales)
|
this.initI18n(lang, locales)
|
||||||
}
|
}
|
||||||
|
|
||||||
private initI18n (lang: string = this.defaultLanguage, locales: ILocales) {
|
private initI18n(lang: string = this.defaultLanguage, locales: ILocales) {
|
||||||
const objectAdapter = new ObjectAdapter({
|
const objectAdapter = new ObjectAdapter({
|
||||||
[lang]: locales
|
[lang]: locales
|
||||||
})
|
})
|
||||||
@@ -87,15 +87,15 @@ class I18nManager {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
T (key: ILocalesKey, args: IStringKeyMap = {}): string {
|
T(key: ILocalesKey, args: IStringKeyMap = {}): string {
|
||||||
return this.i18n?.translate(key, args) || key
|
return this.i18n?.translate(key, args) || key
|
||||||
}
|
}
|
||||||
|
|
||||||
get languageList () {
|
get languageList() {
|
||||||
return this.i18nFileList
|
return this.i18nFileList
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentLocales () {
|
getCurrentLocales() {
|
||||||
return {
|
return {
|
||||||
lang: this.currentLanguage,
|
lang: this.currentLanguage,
|
||||||
locales: this.getLocales(this.currentLanguage)
|
locales: this.getLocales(this.currentLanguage)
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { lifeCycle } from '~/lifeCycle'
|
import { lifeCycle } from '~/lifeCycle'
|
||||||
|
|
||||||
lifeCycle.launchApp()
|
lifeCycle.launchApp()
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ process.on('unhandledRejection', (error: any) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// acconrding to https://github.com/Molunerfinn/PicGo/commit/7363be798cfef11e980934e542817ff1d6c04389#diff-896d0db4fbd446798fbffec14d456b4cd98d4c72c46856c770a585fa7ab0926f
|
// acconrding to https://github.com/Molunerfinn/PicGo/commit/7363be798cfef11e980934e542817ff1d6c04389#diff-896d0db4fbd446798fbffec14d456b4cd98d4c72c46856c770a585fa7ab0926f
|
||||||
function bootstrapEPIPESuppression () {
|
function bootstrapEPIPESuppression() {
|
||||||
let suppressing = false
|
let suppressing = false
|
||||||
function logEPIPEErrorOnce () {
|
function logEPIPEErrorOnce() {
|
||||||
if (suppressing) {
|
if (suppressing) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -41,11 +41,11 @@ function bootstrapEPIPESuppression () {
|
|||||||
|
|
||||||
bootstrapEPIPESuppression()
|
bootstrapEPIPESuppression()
|
||||||
|
|
||||||
function epipeBomb (stream: any, callback: any) {
|
function epipeBomb(stream: any, callback: any) {
|
||||||
if (stream == null) stream = process.stdout
|
if (stream == null) stream = process.stdout
|
||||||
if (callback == null) callback = process.exit
|
if (callback == null) callback = process.exit
|
||||||
|
|
||||||
function epipeFilter (err: any) {
|
function epipeFilter(err: any) {
|
||||||
if (err.code === 'EPIPE') return callback()
|
if (err.code === 'EPIPE') return callback()
|
||||||
|
|
||||||
// If there's more than one error handler (ie, us),
|
// If there's more than one error handler (ie, us),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { shellPathSync } from 'shell-path'
|
import { shellPathSync } from 'shell-path'
|
||||||
|
|
||||||
export default function fixPath () {
|
export default function fixPath() {
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,354 +1,360 @@
|
|||||||
import '~/lifeCycle/errorHandler'
|
import '~/lifeCycle/errorHandler'
|
||||||
|
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
|
|
||||||
import bus from '@core/bus'
|
import bus from '@core/bus'
|
||||||
import db from '@core/datastore'
|
import db from '@core/datastore'
|
||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
import logger from '@core/picgo/logger'
|
import logger from '@core/picgo/logger'
|
||||||
import { remoteNoticeHandler } from 'apis/app/remoteNotice'
|
import { remoteNoticeHandler } from 'apis/app/remoteNotice'
|
||||||
import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler'
|
import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler'
|
||||||
import { createTray, setDockMenu } from 'apis/app/system'
|
import { createTray, setDockMenu } from 'apis/app/system'
|
||||||
import { uploadChoosedFiles, uploadClipboardFiles } from 'apis/app/uploader/apis'
|
import { uploadChoosedFiles, uploadClipboardFiles } from 'apis/app/uploader/apis'
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { app, dialog, globalShortcut, Notification, protocol, screen, shell } from 'electron'
|
import { app, dialog, globalShortcut, Notification, protocol, screen, shell } from 'electron'
|
||||||
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
|
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
|
||||||
import updater from 'electron-updater'
|
import updater from 'electron-updater'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
|
||||||
import busEventList from '~/events/busEventList'
|
import busEventList from '~/events/busEventList'
|
||||||
import { rpcServer } from '~/events/rpc'
|
import { rpcServer } from '~/events/rpc'
|
||||||
import { startFileServer, stopFileServer } from '~/fileServer'
|
import { startFileServer, stopFileServer } from '~/fileServer'
|
||||||
import { T as $t } from '~/i18n'
|
import { T as $t } from '~/i18n'
|
||||||
import fixPath from '~/lifeCycle/fixPath'
|
import fixPath from '~/lifeCycle/fixPath'
|
||||||
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
import UpDownTaskQueue from '~/manage/datastore/upDownTaskQueue'
|
||||||
import getManageApi from '~/manage/Main'
|
import getManageApi from '~/manage/Main'
|
||||||
import { clearTempFolder } from '~/manage/utils/common'
|
import { clearTempFolder } from '~/manage/utils/common'
|
||||||
import server from '~/server/index'
|
import server from '~/server/index'
|
||||||
import webServer from '~/server/webServer'
|
import webServer from '~/server/webServer'
|
||||||
import beforeOpen from '~/utils/beforeOpen'
|
import beforeOpen from '~/utils/beforeOpen'
|
||||||
import clipboardPoll from '~/utils/clipboardPoll'
|
import clipboardPoll from '~/utils/clipboardPoll'
|
||||||
import { configPaths } from '~/utils/configPaths'
|
import { configPaths } from '~/utils/configPaths'
|
||||||
import { II18nLanguage, IRemoteNoticeTriggerHook, ISartMode, IWindowList } from '~/utils/enum'
|
import { II18nLanguage, IRemoteNoticeTriggerHook, ISartMode, IWindowList } from '~/utils/enum'
|
||||||
import { getUploadFiles } from '~/utils/handleArgv'
|
import { getUploadFiles } from '~/utils/handleArgv'
|
||||||
import { initI18n } from '~/utils/handleI18n'
|
import { initI18n } from '~/utils/handleI18n'
|
||||||
import { notificationList } from '~/utils/notification'
|
import { notificationList } from '~/utils/notification'
|
||||||
import { MemoryMonitor } from '~/utils/performanceOptimizer'
|
import { MemoryMonitor } from '~/utils/performanceOptimizer'
|
||||||
import { CLIPBOARD_IMAGE_FOLDER } from '~/utils/static'
|
import { CLIPBOARD_IMAGE_FOLDER } from '~/utils/static'
|
||||||
import updateChecker from '~/utils/updateChecker'
|
import updateChecker from '~/utils/updateChecker'
|
||||||
|
|
||||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||||
|
|
||||||
const handleStartUpFiles = (argv: string[], cwd: string) => {
|
const handleStartUpFiles = (argv: string[], cwd: string) => {
|
||||||
const files = getUploadFiles(argv, cwd, logger)
|
const files = getUploadFiles(argv, cwd, logger)
|
||||||
|
|
||||||
if (files === null) {
|
if (files === null) {
|
||||||
logger.info('cli -> uploading file from clipboard')
|
logger.info('cli -> uploading file from clipboard')
|
||||||
uploadClipboardFiles()
|
uploadClipboardFiles()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files.length > 0) {
|
if (files.length > 0) {
|
||||||
logger.info('cli -> uploading files from cli', ...files.map(file => file.path))
|
logger.info('cli -> uploading files from cli', ...files.map(file => file.path))
|
||||||
const win = windowManager.getAvailableWindow()
|
const win = windowManager.getAvailableWindow()
|
||||||
uploadChoosedFiles(win.webContents, files)
|
uploadChoosedFiles(win.webContents, files)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
updater.autoUpdater.setFeedURL({
|
updater.autoUpdater.setFeedURL({
|
||||||
provider: 'generic',
|
provider: 'generic',
|
||||||
url: 'https://release.piclist.cn/latest',
|
url: 'https://release.piclist.cn/latest',
|
||||||
channel: 'latest'
|
channel: 'latest'
|
||||||
})
|
})
|
||||||
|
|
||||||
updater.autoUpdater.autoDownload = false
|
updater.autoUpdater.autoDownload = false
|
||||||
|
|
||||||
updater.autoUpdater.on('update-available', async (info: updater.UpdateInfo) => {
|
updater.autoUpdater.on('update-available', async (info: updater.UpdateInfo) => {
|
||||||
const lang = db.get(configPaths.settings.language) || II18nLanguage.ZH_CN
|
const lang = db.get(configPaths.settings.language) || II18nLanguage.ZH_CN
|
||||||
let updateLog = ''
|
let updateLog = ''
|
||||||
try {
|
try {
|
||||||
const url =
|
const url =
|
||||||
lang === II18nLanguage.ZH_CN
|
lang === II18nLanguage.ZH_CN
|
||||||
? 'https://release.piclist.cn/currentVersion.md'
|
? 'https://release.piclist.cn/currentVersion.md'
|
||||||
: 'https://release.piclist.cn/currentVersion_en.md'
|
: 'https://release.piclist.cn/currentVersion_en.md'
|
||||||
const res = await axios.get(url)
|
const res = await axios.get(url)
|
||||||
updateLog = res.data
|
updateLog = res.data
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxLogLength = 800
|
const maxLogLength = 800
|
||||||
let displayLog = updateLog
|
let displayLog = updateLog
|
||||||
let truncatedNote = ''
|
let truncatedNote = ''
|
||||||
|
|
||||||
if (updateLog.length > maxLogLength) {
|
if (updateLog.length > maxLogLength) {
|
||||||
const truncatePoint = updateLog.lastIndexOf('\n', maxLogLength)
|
const truncatePoint = updateLog.lastIndexOf('\n', maxLogLength)
|
||||||
displayLog = updateLog.substring(0, truncatePoint > 0 ? truncatePoint : maxLogLength)
|
displayLog = updateLog.substring(0, truncatePoint > 0 ? truncatePoint : maxLogLength)
|
||||||
truncatedNote =
|
truncatedNote =
|
||||||
lang === II18nLanguage.ZH_CN
|
lang === II18nLanguage.ZH_CN
|
||||||
? '\n\n... (更多详情请查看完整更新日志)'
|
? '\n\n... (更多详情请查看完整更新日志)'
|
||||||
: '\n\n... (See full changelog for more details)'
|
: '\n\n... (See full changelog for more details)'
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog
|
dialog
|
||||||
.showMessageBox({
|
.showMessageBox({
|
||||||
type: 'info',
|
type: 'info',
|
||||||
title: $t('FIND_NEW_VERSION'),
|
title: $t('FIND_NEW_VERSION'),
|
||||||
buttons: ['Yes', 'Go to download page'],
|
buttons: ['Yes', 'Go to download page'],
|
||||||
message:
|
message:
|
||||||
$t('TIPS_FIND_NEW_VERSION', {
|
$t('TIPS_FIND_NEW_VERSION', {
|
||||||
v: info.version
|
v: info.version
|
||||||
}) +
|
}) +
|
||||||
'\n\n' +
|
'\n\n' +
|
||||||
displayLog +
|
displayLog +
|
||||||
truncatedNote,
|
truncatedNote,
|
||||||
checkboxLabel: $t('NO_MORE_NOTICE'),
|
checkboxLabel: $t('NO_MORE_NOTICE'),
|
||||||
checkboxChecked: false
|
checkboxChecked: false
|
||||||
})
|
})
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (result.response === 0) {
|
if (result.response === 0) {
|
||||||
updater.autoUpdater.downloadUpdate()
|
updater.autoUpdater.downloadUpdate()
|
||||||
} else {
|
} else {
|
||||||
shell.openExternal('https://github.com/Kuingsmile/PicList/releases/latest')
|
shell.openExternal('https://github.com/Kuingsmile/PicList/releases/latest')
|
||||||
}
|
}
|
||||||
db.set(configPaths.settings.showUpdateTip, !result.checkboxChecked)
|
db.set(configPaths.settings.showUpdateTip, !result.checkboxChecked)
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
updater.autoUpdater.on('download-progress', progressObj => {
|
updater.autoUpdater.on('download-progress', progressObj => {
|
||||||
const percent = {
|
const percent = {
|
||||||
progress: progressObj.percent
|
progress: progressObj.percent
|
||||||
}
|
}
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
window.webContents.send('updateProgress', percent)
|
window.webContents.send('updateProgress', percent)
|
||||||
})
|
})
|
||||||
|
|
||||||
updater.autoUpdater.on('update-downloaded', () => {
|
updater.autoUpdater.on('update-downloaded', () => {
|
||||||
dialog
|
dialog
|
||||||
.showMessageBox({
|
.showMessageBox({
|
||||||
type: 'info',
|
type: 'info',
|
||||||
title: $t('UPDATE_DOWNLOADED'),
|
title: $t('UPDATE_DOWNLOADED'),
|
||||||
buttons: ['Yes', 'No'],
|
buttons: ['Yes', 'No'],
|
||||||
message: $t('TIPS_UPDATE_DOWNLOADED')
|
message: $t('TIPS_UPDATE_DOWNLOADED')
|
||||||
})
|
})
|
||||||
.then(result => {
|
.then(result => {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
window.webContents.send('updateProgress', { progress: 100 })
|
window.webContents.send('updateProgress', { progress: 100 })
|
||||||
if (result.response === 0) {
|
if (result.response === 0) {
|
||||||
updater.autoUpdater.quitAndInstall()
|
updater.autoUpdater.quitAndInstall()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
updater.autoUpdater.on('error', err => {
|
updater.autoUpdater.on('error', err => {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
})
|
})
|
||||||
|
|
||||||
class LifeCycle {
|
class LifeCycle {
|
||||||
async #beforeReady () {
|
async #beforeReady() {
|
||||||
protocol.registerSchemesAsPrivileged([{ scheme: 'picgo', privileges: { secure: true, standard: true } }])
|
protocol.registerSchemesAsPrivileged([{ scheme: 'picgo', privileges: { secure: true, standard: true } }])
|
||||||
// fix the $PATH in macOS & linux
|
// fix the $PATH in macOS & linux
|
||||||
fixPath()
|
fixPath()
|
||||||
beforeOpen()
|
beforeOpen()
|
||||||
getManageApi()
|
getManageApi()
|
||||||
UpDownTaskQueue.getInstance()
|
UpDownTaskQueue.getInstance()
|
||||||
initI18n()
|
initI18n()
|
||||||
rpcServer.start()
|
rpcServer.start()
|
||||||
busEventList.listen()
|
busEventList.listen()
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
MemoryMonitor.start(30000)
|
MemoryMonitor.start(30000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#onReady () {
|
#onReady() {
|
||||||
const readyFunction = async () => {
|
const readyFunction = async () => {
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
installExtension(VUEJS_DEVTOOLS).catch(err => {
|
installExtension(VUEJS_DEVTOOLS).catch(err => {
|
||||||
logger.error('An error occurred: ', err)
|
logger.error('An error occurred: ', err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
windowManager.create(IWindowList.TRAY_WINDOW)
|
windowManager.create(IWindowList.TRAY_WINDOW)
|
||||||
windowManager.create(IWindowList.SETTING_WINDOW)
|
windowManager.create(IWindowList.SETTING_WINDOW)
|
||||||
const isAutoListenClipboard = db.get(configPaths.settings.isAutoListenClipboard) || false
|
const isAutoListenClipboard = db.get(configPaths.settings.isAutoListenClipboard) || false
|
||||||
const ClipboardWatcher = clipboardPoll
|
const ClipboardWatcher = clipboardPoll
|
||||||
if (isAutoListenClipboard) {
|
if (isAutoListenClipboard) {
|
||||||
db.set(configPaths.settings.isListeningClipboard, true)
|
db.set(configPaths.settings.isListeningClipboard, true)
|
||||||
ClipboardWatcher.startListening()
|
ClipboardWatcher.startListening()
|
||||||
ClipboardWatcher.on('change', () => {
|
ClipboardWatcher.on('change', () => {
|
||||||
picgo.log.info('clipboard changed')
|
picgo.log.info('clipboard changed')
|
||||||
uploadClipboardFiles()
|
uploadClipboardFiles()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
db.set(configPaths.settings.isListeningClipboard, false)
|
db.set(configPaths.settings.isListeningClipboard, false)
|
||||||
}
|
}
|
||||||
const isHideDock = db.get(configPaths.settings.isHideDock) || false
|
const isHideDock = db.get(configPaths.settings.isHideDock) || false
|
||||||
let startMode = db.get(configPaths.settings.startMode) || ISartMode.QUIET
|
let startMode = db.get(configPaths.settings.startMode) || ISartMode.QUIET
|
||||||
if (process.platform === 'darwin' && startMode === ISartMode.MINI) {
|
if (process.platform === 'darwin' && startMode === ISartMode.MINI) {
|
||||||
startMode = ISartMode.QUIET
|
startMode = ISartMode.QUIET
|
||||||
}
|
}
|
||||||
const currentPicBed = db.get(configPaths.picBed.uploader) || db.get(configPaths.picBed.current) || 'smms'
|
const currentPicBed = db.get(configPaths.picBed.uploader) || db.get(configPaths.picBed.current) || 'smms'
|
||||||
const currentPicBedConfig = db.get(`picBed.${currentPicBed}`)?._configName || 'Default'
|
const currentPicBedConfig = db.get(`picBed.${currentPicBed}`)?._configName || 'Default'
|
||||||
const tooltip = `${currentPicBed} ${currentPicBedConfig}`
|
const tooltip = `${currentPicBed} ${currentPicBedConfig}`
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
isHideDock ? app.dock?.hide() : setDockMenu()
|
isHideDock ? app.dock?.hide() : setDockMenu()
|
||||||
startMode !== ISartMode.NO_TRAY && createTray(tooltip)
|
startMode !== ISartMode.NO_TRAY && createTray(tooltip)
|
||||||
} else {
|
} else {
|
||||||
createTray(tooltip)
|
createTray(tooltip)
|
||||||
}
|
}
|
||||||
db.set(configPaths.needReload, false)
|
db.set(configPaths.needReload, false)
|
||||||
updateChecker()
|
updateChecker()
|
||||||
// 不需要阻塞
|
// 不需要阻塞
|
||||||
process.nextTick(() => {
|
process.nextTick(() => {
|
||||||
shortKeyHandler.init()
|
shortKeyHandler.init()
|
||||||
})
|
})
|
||||||
server.startup()
|
server.startup()
|
||||||
webServer.start()
|
webServer.start()
|
||||||
startFileServer()
|
startFileServer()
|
||||||
if (process.env.NODE_ENV !== 'development') {
|
if (process.env.NODE_ENV !== 'development') {
|
||||||
handleStartUpFiles(process.argv, process.cwd())
|
handleStartUpFiles(process.argv, process.cwd())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notificationList && notificationList.length > 0) {
|
if (notificationList && notificationList.length > 0) {
|
||||||
while (notificationList.length) {
|
while (notificationList.length) {
|
||||||
const option = notificationList.pop()
|
const option = notificationList.pop()
|
||||||
const notice = new Notification(option!)
|
const notice = new Notification(option!)
|
||||||
notice.show()
|
notice.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await remoteNoticeHandler.init()
|
await remoteNoticeHandler.init()
|
||||||
remoteNoticeHandler.triggerHook(IRemoteNoticeTriggerHook.APP_START)
|
remoteNoticeHandler.triggerHook(IRemoteNoticeTriggerHook.APP_START)
|
||||||
if (startMode === ISartMode.MINI && process.platform !== 'darwin') {
|
if (startMode === ISartMode.MINI && process.platform !== 'darwin') {
|
||||||
windowManager.create(IWindowList.MINI_WINDOW)
|
windowManager.create(IWindowList.MINI_WINDOW)
|
||||||
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)!
|
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)!
|
||||||
miniWindow.removeAllListeners()
|
miniWindow.removeAllListeners()
|
||||||
if (db.get(configPaths.settings.miniWindowOntop)) {
|
if (db.get(configPaths.settings.miniWindowOntop)) {
|
||||||
miniWindow.setAlwaysOnTop(true)
|
miniWindow.setAlwaysOnTop(true)
|
||||||
}
|
}
|
||||||
const { width, height } = screen.getPrimaryDisplay().workAreaSize
|
const { width, height } = screen.getPrimaryDisplay().workAreaSize
|
||||||
const lastPosition = db.get(configPaths.settings.miniWindowPosition)
|
const lastPosition = db.get(configPaths.settings.miniWindowPosition)
|
||||||
if (lastPosition) {
|
if (lastPosition) {
|
||||||
if (lastPosition[0] < 0 || lastPosition[0] > width || lastPosition[1] < 0 || lastPosition[1] > height) {
|
if (lastPosition[0] < 0 || lastPosition[0] > width || lastPosition[1] < 0 || lastPosition[1] > height) {
|
||||||
miniWindow.setPosition(width - 100, height - 100)
|
miniWindow.setPosition(width - 100, height - 100)
|
||||||
db.set(configPaths.settings.miniWindowPosition, [width - 100, height - 100])
|
db.set(configPaths.settings.miniWindowPosition, [width - 100, height - 100])
|
||||||
} else if (lastPosition[0] + miniWindow.getSize()[0] > width || lastPosition[1] + miniWindow.getSize()[1] > height) {
|
} else if (
|
||||||
miniWindow.setPosition(width - miniWindow.getSize()[0], height - miniWindow.getSize()[1])
|
lastPosition[0] + miniWindow.getSize()[0] > width ||
|
||||||
db.set(configPaths.settings.miniWindowPosition, [width - miniWindow.getSize()[0], height - miniWindow.getSize()[1]])
|
lastPosition[1] + miniWindow.getSize()[1] > height
|
||||||
} else {
|
) {
|
||||||
miniWindow.setPosition(lastPosition[0], lastPosition[1])
|
miniWindow.setPosition(width - miniWindow.getSize()[0], height - miniWindow.getSize()[1])
|
||||||
}
|
db.set(configPaths.settings.miniWindowPosition, [
|
||||||
} else {
|
width - miniWindow.getSize()[0],
|
||||||
miniWindow.setPosition(width - 100, height - 100)
|
height - miniWindow.getSize()[1]
|
||||||
}
|
])
|
||||||
const setPositionFunc = () => {
|
} else {
|
||||||
const position = miniWindow.getPosition()
|
miniWindow.setPosition(lastPosition[0], lastPosition[1])
|
||||||
db.set(configPaths.settings.miniWindowPosition, position)
|
}
|
||||||
}
|
} else {
|
||||||
miniWindow.on('close', setPositionFunc)
|
miniWindow.setPosition(width - 100, height - 100)
|
||||||
miniWindow.on('move', setPositionFunc)
|
}
|
||||||
miniWindow.show()
|
const setPositionFunc = () => {
|
||||||
miniWindow.focus()
|
const position = miniWindow.getPosition()
|
||||||
} else if (startMode === ISartMode.MAIN) {
|
db.set(configPaths.settings.miniWindowPosition, position)
|
||||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
}
|
||||||
settingWindow.show()
|
miniWindow.on('close', setPositionFunc)
|
||||||
settingWindow.focus()
|
miniWindow.on('move', setPositionFunc)
|
||||||
}
|
miniWindow.show()
|
||||||
const clipboardDir = path.join(picgo.baseDir, CLIPBOARD_IMAGE_FOLDER)
|
miniWindow.focus()
|
||||||
fs.emptyDir(clipboardDir)
|
} else if (startMode === ISartMode.MAIN) {
|
||||||
}
|
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
app.whenReady().then(readyFunction)
|
settingWindow.show()
|
||||||
}
|
settingWindow.focus()
|
||||||
|
}
|
||||||
#onRunning () {
|
const clipboardDir = path.join(picgo.baseDir, CLIPBOARD_IMAGE_FOLDER)
|
||||||
app.on('second-instance', (_, commandLine, workingDirectory) => {
|
fs.emptyDir(clipboardDir)
|
||||||
logger.info('detect second instance')
|
}
|
||||||
const result = handleStartUpFiles(commandLine, workingDirectory)
|
app.whenReady().then(readyFunction)
|
||||||
if (!result) {
|
}
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
|
||||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
#onRunning() {
|
||||||
if (settingWindow.isMinimized()) {
|
app.on('second-instance', (_, commandLine, workingDirectory) => {
|
||||||
settingWindow.restore()
|
logger.info('detect second instance')
|
||||||
}
|
const result = handleStartUpFiles(commandLine, workingDirectory)
|
||||||
settingWindow.focus()
|
if (!result) {
|
||||||
}
|
if (windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||||
}
|
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
})
|
if (settingWindow.isMinimized()) {
|
||||||
app.on('activate', () => {
|
settingWindow.restore()
|
||||||
if (!windowManager.has(IWindowList.TRAY_WINDOW)) {
|
}
|
||||||
windowManager.create(IWindowList.TRAY_WINDOW)
|
settingWindow.focus()
|
||||||
}
|
}
|
||||||
if (!windowManager.has(IWindowList.SETTING_WINDOW)) {
|
}
|
||||||
windowManager.create(IWindowList.SETTING_WINDOW)
|
})
|
||||||
}
|
app.on('activate', () => {
|
||||||
})
|
if (!windowManager.has(IWindowList.TRAY_WINDOW)) {
|
||||||
app.setLoginItemSettings({
|
windowManager.create(IWindowList.TRAY_WINDOW)
|
||||||
openAtLogin: db.get(configPaths.settings.autoStart) || false
|
}
|
||||||
})
|
if (!windowManager.has(IWindowList.SETTING_WINDOW)) {
|
||||||
if (process.platform === 'win32') {
|
windowManager.create(IWindowList.SETTING_WINDOW)
|
||||||
app.setAppUserModelId('com.kuingsmile.piclist')
|
}
|
||||||
}
|
})
|
||||||
|
app.setLoginItemSettings({
|
||||||
if (process.env.XDG_CURRENT_DESKTOP && process.env.XDG_CURRENT_DESKTOP.includes('Unity')) {
|
openAtLogin: db.get(configPaths.settings.autoStart) || false
|
||||||
process.env.XDG_CURRENT_DESKTOP = 'Unity'
|
})
|
||||||
}
|
if (process.platform === 'win32') {
|
||||||
}
|
app.setAppUserModelId('com.kuingsmile.piclist')
|
||||||
|
}
|
||||||
#onQuit () {
|
|
||||||
app.on('window-all-closed', () => {
|
if (process.env.XDG_CURRENT_DESKTOP && process.env.XDG_CURRENT_DESKTOP.includes('Unity')) {
|
||||||
if (process.platform !== 'darwin') {
|
process.env.XDG_CURRENT_DESKTOP = 'Unity'
|
||||||
app.quit()
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
#onQuit() {
|
||||||
app.on('will-quit', () => {
|
app.on('window-all-closed', () => {
|
||||||
UpDownTaskQueue.getInstance().persist()
|
if (process.platform !== 'darwin') {
|
||||||
clearTempFolder()
|
app.quit()
|
||||||
globalShortcut.unregisterAll()
|
}
|
||||||
bus.removeAllListeners()
|
})
|
||||||
server.shutdown()
|
|
||||||
webServer.stop()
|
app.on('will-quit', () => {
|
||||||
stopFileServer()
|
UpDownTaskQueue.getInstance().persist()
|
||||||
MemoryMonitor.stop()
|
clearTempFolder()
|
||||||
})
|
globalShortcut.unregisterAll()
|
||||||
// Exit cleanly on request from parent process in development mode.
|
bus.removeAllListeners()
|
||||||
if (isDevelopment) {
|
server.shutdown()
|
||||||
if (process.platform === 'win32') {
|
webServer.stop()
|
||||||
process.on('message', data => {
|
stopFileServer()
|
||||||
if (data === 'graceful-exit') {
|
MemoryMonitor.stop()
|
||||||
app.quit()
|
})
|
||||||
}
|
// Exit cleanly on request from parent process in development mode.
|
||||||
})
|
if (isDevelopment) {
|
||||||
} else {
|
if (process.platform === 'win32') {
|
||||||
process.on('SIGTERM', () => {
|
process.on('message', data => {
|
||||||
app.quit()
|
if (data === 'graceful-exit') {
|
||||||
})
|
app.quit()
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
} else {
|
||||||
|
process.on('SIGTERM', () => {
|
||||||
async launchApp () {
|
app.quit()
|
||||||
const gotTheLock = app.requestSingleInstanceLock()
|
})
|
||||||
if (!gotTheLock) {
|
}
|
||||||
app.quit()
|
}
|
||||||
} else {
|
}
|
||||||
await this.#beforeReady()
|
|
||||||
this.#onReady()
|
async launchApp() {
|
||||||
this.#onRunning()
|
const gotTheLock = app.requestSingleInstanceLock()
|
||||||
this.#onQuit()
|
if (!gotTheLock) {
|
||||||
}
|
app.quit()
|
||||||
}
|
} else {
|
||||||
}
|
await this.#beforeReady()
|
||||||
|
this.#onReady()
|
||||||
const lifeCycle = new LifeCycle()
|
this.#onRunning()
|
||||||
|
this.#onQuit()
|
||||||
export { lifeCycle }
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const lifeCycle = new LifeCycle()
|
||||||
|
|
||||||
|
export { lifeCycle }
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class AliyunApi {
|
|||||||
timeOut = 30000
|
timeOut = 30000
|
||||||
logger: ManageLogger
|
logger: ManageLogger
|
||||||
|
|
||||||
constructor (accessKeyId: string, accessKeySecret: string, logger: ManageLogger) {
|
constructor(accessKeyId: string, accessKeySecret: string, logger: ManageLogger) {
|
||||||
this.ctx = new OSS({
|
this.ctx = new OSS({
|
||||||
accessKeyId,
|
accessKeyId,
|
||||||
accessKeySecret,
|
accessKeySecret,
|
||||||
@@ -39,7 +39,7 @@ class AliyunApi {
|
|||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFolder (item: string, slicedPrefix: string, urlPrefix: string): any {
|
formatFolder(item: string, slicedPrefix: string, urlPrefix: string): any {
|
||||||
return {
|
return {
|
||||||
key: item,
|
key: item,
|
||||||
url: `${urlPrefix}/${item}`,
|
url: `${urlPrefix}/${item}`,
|
||||||
@@ -54,7 +54,7 @@ class AliyunApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFile (item: OSS.ObjectMeta, slicedPrefix: string, urlPrefix: string): any {
|
formatFile(item: OSS.ObjectMeta, slicedPrefix: string, urlPrefix: string): any {
|
||||||
const fileName = item.name.replace(slicedPrefix, '')
|
const fileName = item.name.replace(slicedPrefix, '')
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
@@ -71,7 +71,7 @@ class AliyunApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getCanonicalizedOSSHeaders (headers: IStringKeyMap) {
|
getCanonicalizedOSSHeaders(headers: IStringKeyMap) {
|
||||||
const lowerCaseHeaders = Object.keys(headers).reduce((acc, key) => {
|
const lowerCaseHeaders = Object.keys(headers).reduce((acc, key) => {
|
||||||
acc[key.toLowerCase()] = headers[key]
|
acc[key.toLowerCase()] = headers[key]
|
||||||
return acc
|
return acc
|
||||||
@@ -84,7 +84,7 @@ class AliyunApi {
|
|||||||
return canonicalizedOSSHeaders
|
return canonicalizedOSSHeaders
|
||||||
}
|
}
|
||||||
|
|
||||||
authorization (
|
authorization(
|
||||||
method: string,
|
method: string,
|
||||||
canonicalizedResource: string,
|
canonicalizedResource: string,
|
||||||
headers: IStringKeyMap,
|
headers: IStringKeyMap,
|
||||||
@@ -96,7 +96,7 @@ class AliyunApi {
|
|||||||
return `OSS ${this.accessKeyId}:${hmacSha1Base64(this.accessKeySecret, stringToSign)}`
|
return `OSS ${this.accessKeyId}:${hmacSha1Base64(this.accessKeySecret, stringToSign)}`
|
||||||
}
|
}
|
||||||
|
|
||||||
getNewCtx (region: string, bucket: string) {
|
getNewCtx(region: string, bucket: string) {
|
||||||
return new OSS({
|
return new OSS({
|
||||||
accessKeyId: this.accessKeyId,
|
accessKeyId: this.accessKeyId,
|
||||||
accessKeySecret: this.accessKeySecret,
|
accessKeySecret: this.accessKeySecret,
|
||||||
@@ -109,7 +109,7 @@ class AliyunApi {
|
|||||||
/**
|
/**
|
||||||
* 获取存储桶列表
|
* 获取存储桶列表
|
||||||
*/
|
*/
|
||||||
async getBucketList (): Promise<any> {
|
async getBucketList(): Promise<any> {
|
||||||
const getBuckets = async (marker?: string) => {
|
const getBuckets = async (marker?: string) => {
|
||||||
const res = (await this.ctx.listBuckets({
|
const res = (await this.ctx.listBuckets({
|
||||||
marker,
|
marker,
|
||||||
@@ -143,7 +143,7 @@ class AliyunApi {
|
|||||||
/**
|
/**
|
||||||
* 获取自定义域名
|
* 获取自定义域名
|
||||||
*/
|
*/
|
||||||
async getBucketDomain (param: IStringKeyMap): Promise<any> {
|
async getBucketDomain(param: IStringKeyMap): Promise<any> {
|
||||||
const headers = {
|
const headers = {
|
||||||
Date: new Date().toUTCString()
|
Date: new Date().toUTCString()
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ class AliyunApi {
|
|||||||
* @description
|
* @description
|
||||||
* acl: private | publicRead | publicReadWrite
|
* acl: private | publicRead | publicReadWrite
|
||||||
*/
|
*/
|
||||||
async createBucket (configMap: IStringKeyMap): Promise<boolean> {
|
async createBucket(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const client = new OSS({
|
const client = new OSS({
|
||||||
accessKeyId: this.accessKeyId,
|
accessKeyId: this.accessKeyId,
|
||||||
accessKeySecret: this.accessKeySecret,
|
accessKeySecret: this.accessKeySecret,
|
||||||
@@ -207,7 +207,7 @@ class AliyunApi {
|
|||||||
return res?.res?.status === 200
|
return res?.res?.status === 200
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListRecursively(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const {
|
const {
|
||||||
bucketName: bucket,
|
bucketName: bucket,
|
||||||
@@ -262,7 +262,7 @@ class AliyunApi {
|
|||||||
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const {
|
const {
|
||||||
bucketName: bucket,
|
bucketName: bucket,
|
||||||
@@ -336,7 +336,7 @@ class AliyunApi {
|
|||||||
* customUrl: string
|
* customUrl: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async getBucketFileList (configMap: IStringKeyMap): Promise<any> {
|
async getBucketFileList(configMap: IStringKeyMap): Promise<any> {
|
||||||
const {
|
const {
|
||||||
bucketName: bucket,
|
bucketName: bucket,
|
||||||
bucketConfig: { Location: region },
|
bucketConfig: { Location: region },
|
||||||
@@ -393,7 +393,7 @@ class AliyunApi {
|
|||||||
* newKey: string
|
* newKey: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async renameBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async renameBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, region, oldKey, newKey } = configMap
|
const { bucketName, region, oldKey, newKey } = configMap
|
||||||
const client = this.getNewCtx(region, bucketName)
|
const client = this.getNewCtx(region, bucketName)
|
||||||
const copyRes = (await client.copy(newKey, oldKey)) as any
|
const copyRes = (await client.copy(newKey, oldKey)) as any
|
||||||
@@ -413,7 +413,7 @@ class AliyunApi {
|
|||||||
* key: string
|
* key: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async deleteBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, region, key } = configMap
|
const { bucketName, region, key } = configMap
|
||||||
const client = this.getNewCtx(region, bucketName)
|
const client = this.getNewCtx(region, bucketName)
|
||||||
const res = (await client.delete(key)) as any
|
const res = (await client.delete(key)) as any
|
||||||
@@ -424,7 +424,7 @@ class AliyunApi {
|
|||||||
* 删除文件夹
|
* 删除文件夹
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async deleteBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, region, key } = configMap
|
const { bucketName, region, key } = configMap
|
||||||
const client = this.getNewCtx(region, bucketName)
|
const client = this.getNewCtx(region, bucketName)
|
||||||
let marker
|
let marker
|
||||||
@@ -486,7 +486,7 @@ class AliyunApi {
|
|||||||
* customUrl: string
|
* customUrl: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async getPreSignedUrl (configMap: IStringKeyMap): Promise<string> {
|
async getPreSignedUrl(configMap: IStringKeyMap): Promise<string> {
|
||||||
const { bucketName, region, key, expires, customUrl } = configMap
|
const { bucketName, region, key, expires, customUrl } = configMap
|
||||||
const client = this.getNewCtx(region, bucketName)
|
const client = this.getNewCtx(region, bucketName)
|
||||||
const res = client.signatureUrl(key, {
|
const res = client.signatureUrl(key, {
|
||||||
@@ -499,7 +499,7 @@ class AliyunApi {
|
|||||||
* 上传文件
|
* 上传文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async uploadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async uploadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { fileArray } = configMap
|
const { fileArray } = configMap
|
||||||
// fileArray = [{
|
// fileArray = [{
|
||||||
// bucketName: string,
|
// bucketName: string,
|
||||||
@@ -586,7 +586,7 @@ class AliyunApi {
|
|||||||
* 新建文件夹
|
* 新建文件夹
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async createBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async createBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, region, key } = configMap
|
const { bucketName, region, key } = configMap
|
||||||
const client = this.getNewCtx(region, bucketName)
|
const client = this.getNewCtx(region, bucketName)
|
||||||
const res = (await client.put(key, Buffer.from(''))) as any
|
const res = (await client.put(key, Buffer.from(''))) as any
|
||||||
@@ -597,7 +597,7 @@ class AliyunApi {
|
|||||||
* 下载文件
|
* 下载文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async downloadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async downloadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
const promises = [] as any
|
const promises = [] as any
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class GithubApi {
|
|||||||
baseUrl = 'https://api.github.com'
|
baseUrl = 'https://api.github.com'
|
||||||
commonHeaders: IStringKeyMap
|
commonHeaders: IStringKeyMap
|
||||||
|
|
||||||
constructor (token: string, username: string, proxy: string | undefined, logger: ManageLogger) {
|
constructor(token: string, username: string, proxy: string | undefined, logger: ManageLogger) {
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
this.token = token.startsWith('Bearer ') ? token : `Bearer ${token}`.trim()
|
this.token = token.startsWith('Bearer ') ? token : `Bearer ${token}`.trim()
|
||||||
this.username = username
|
this.username = username
|
||||||
@@ -41,7 +41,7 @@ class GithubApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFolder (item: any, slicedPrefix: string, branch: string, repo: string, cdnUrl: string | undefined) {
|
formatFolder(item: any, slicedPrefix: string, branch: string, repo: string, cdnUrl: string | undefined) {
|
||||||
const key = `${slicedPrefix ? `${slicedPrefix}/` : ''}${item.path}/`
|
const key = `${slicedPrefix ? `${slicedPrefix}/` : ''}${item.path}/`
|
||||||
let rawUrl = ''
|
let rawUrl = ''
|
||||||
const placeholders = ['{username}', '{repo}', '{branch}', '{path}']
|
const placeholders = ['{username}', '{repo}', '{branch}', '{path}']
|
||||||
@@ -78,7 +78,7 @@ class GithubApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFile (item: any, slicedPrefix: string, branch: string, repo: string, cdnUrl: string | undefined) {
|
formatFile(item: any, slicedPrefix: string, branch: string, repo: string, cdnUrl: string | undefined) {
|
||||||
let rawUrl = ''
|
let rawUrl = ''
|
||||||
const placeholders = ['{username}', '{repo}', '{branch}', '{path}']
|
const placeholders = ['{username}', '{repo}', '{branch}', '{path}']
|
||||||
const key = slicedPrefix === '' ? item.path : `${slicedPrefix}/${item.path}`
|
const key = slicedPrefix === '' ? item.path : `${slicedPrefix}/${item.path}`
|
||||||
@@ -119,7 +119,7 @@ class GithubApi {
|
|||||||
/**
|
/**
|
||||||
* get repo list
|
* get repo list
|
||||||
*/
|
*/
|
||||||
async getBucketList (): Promise<any> {
|
async getBucketList(): Promise<any> {
|
||||||
let initPage = 1
|
let initPage = 1
|
||||||
let res
|
let res
|
||||||
const result = [] as any[]
|
const result = [] as any[]
|
||||||
@@ -156,7 +156,7 @@ class GithubApi {
|
|||||||
/**
|
/**
|
||||||
* 获取branch列表
|
* 获取branch列表
|
||||||
*/
|
*/
|
||||||
async getBucketDomain (param: IStringKeyMap): Promise<any> {
|
async getBucketDomain(param: IStringKeyMap): Promise<any> {
|
||||||
const { bucketName: repo } = param
|
const { bucketName: repo } = param
|
||||||
let initPage = 1
|
let initPage = 1
|
||||||
let res
|
let res
|
||||||
@@ -184,7 +184,7 @@ class GithubApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListRecursively(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { bucketName: repo, customUrl: branch, prefix, cancelToken, cdnUrl } = configMap
|
const { bucketName: repo, customUrl: branch, prefix, cancelToken, cdnUrl } = configMap
|
||||||
const slicedPrefix = prefix.replace(/(^\/+|\/+$)/g, '')
|
const slicedPrefix = prefix.replace(/(^\/+|\/+$)/g, '')
|
||||||
@@ -235,7 +235,7 @@ class GithubApi {
|
|||||||
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { bucketName: repo, customUrl: branch, prefix, cancelToken, cdnUrl } = configMap
|
const { bucketName: repo, customUrl: branch, prefix, cancelToken, cdnUrl } = configMap
|
||||||
const slicedPrefix = prefix.replace(/(^\/+|\/+$)/g, '')
|
const slicedPrefix = prefix.replace(/(^\/+|\/+$)/g, '')
|
||||||
@@ -285,7 +285,7 @@ class GithubApi {
|
|||||||
* key: string
|
* key: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async deleteBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName: repo, githubBranch: branch, key, DeleteHash: sha } = configMap
|
const { bucketName: repo, githubBranch: branch, key, DeleteHash: sha } = configMap
|
||||||
const body = {
|
const body = {
|
||||||
message: 'deleted by PicList',
|
message: 'deleted by PicList',
|
||||||
@@ -303,7 +303,7 @@ class GithubApi {
|
|||||||
* create a new tree to delete a folder
|
* create a new tree to delete a folder
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async deleteBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName: repo, githubBranch: branch, key } = configMap
|
const { bucketName: repo, githubBranch: branch, key } = configMap
|
||||||
// get sha of the branch
|
// get sha of the branch
|
||||||
const refRes = (await got(
|
const refRes = (await got(
|
||||||
@@ -412,7 +412,7 @@ class GithubApi {
|
|||||||
* customUrl: string
|
* customUrl: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async getPreSignedUrl (configMap: IStringKeyMap): Promise<string> {
|
async getPreSignedUrl(configMap: IStringKeyMap): Promise<string> {
|
||||||
const { bucketName: repo, customUrl: branch, key, rawUrl, githubPrivate: isPrivate } = configMap
|
const { bucketName: repo, customUrl: branch, key, rawUrl, githubPrivate: isPrivate } = configMap
|
||||||
if (!isPrivate) return rawUrl
|
if (!isPrivate) return rawUrl
|
||||||
const res = (await got(
|
const res = (await got(
|
||||||
@@ -436,7 +436,7 @@ class GithubApi {
|
|||||||
* 新建文件夹
|
* 新建文件夹
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async createBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async createBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName: repo, githubBranch: branch, key } = configMap
|
const { bucketName: repo, githubBranch: branch, key } = configMap
|
||||||
const newFileKey = `${trimPath(key)}/.gitkeep`
|
const newFileKey = `${trimPath(key)}/.gitkeep`
|
||||||
const base64Content = Buffer.from('created by PicList').toString('base64')
|
const base64Content = Buffer.from('created by PicList').toString('base64')
|
||||||
@@ -456,7 +456,7 @@ class GithubApi {
|
|||||||
* 上传文件
|
* 上传文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async uploadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async uploadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { fileArray } = configMap
|
const { fileArray } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
fileArray.forEach((item: any) => {
|
fileArray.forEach((item: any) => {
|
||||||
@@ -505,7 +505,7 @@ class GithubApi {
|
|||||||
* 下载文件
|
* 下载文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async downloadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async downloadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
const promises = [] as any
|
const promises = [] as any
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class ImgurApi {
|
|||||||
idHeaders: any
|
idHeaders: any
|
||||||
baseUrl = 'https://api.imgur.com/3'
|
baseUrl = 'https://api.imgur.com/3'
|
||||||
|
|
||||||
constructor (userName: string, accessToken: string, proxy: any, logger: ManageLogger) {
|
constructor(userName: string, accessToken: string, proxy: any, logger: ManageLogger) {
|
||||||
this.userName = userName
|
this.userName = userName
|
||||||
this.accessToken = accessToken.startsWith('Bearer ') ? accessToken : `Bearer ${accessToken}`
|
this.accessToken = accessToken.startsWith('Bearer ') ? accessToken : `Bearer ${accessToken}`
|
||||||
this.proxy = proxy
|
this.proxy = proxy
|
||||||
@@ -42,7 +42,7 @@ class ImgurApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFile (item: any) {
|
formatFile(item: any) {
|
||||||
const fileName = path.basename(item.link)
|
const fileName = path.basename(item.link)
|
||||||
const isImg = isImage(fileName)
|
const isImg = isImage(fileName)
|
||||||
return {
|
return {
|
||||||
@@ -64,7 +64,7 @@ class ImgurApi {
|
|||||||
/**
|
/**
|
||||||
* get repo list
|
* get repo list
|
||||||
*/
|
*/
|
||||||
async getBucketList (): Promise<any> {
|
async getBucketList(): Promise<any> {
|
||||||
let initPage = 0
|
let initPage = 0
|
||||||
let res
|
let res
|
||||||
const result = [] as any[]
|
const result = [] as any[]
|
||||||
@@ -93,7 +93,7 @@ class ImgurApi {
|
|||||||
return finalResult
|
return finalResult
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const {
|
const {
|
||||||
bucketConfig: { Location: albumHash },
|
bucketConfig: { Location: albumHash },
|
||||||
@@ -153,7 +153,7 @@ class ImgurApi {
|
|||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { DeleteHash: deleteHash } = configMap
|
const { DeleteHash: deleteHash } = configMap
|
||||||
const res = (await got(
|
const res = (await got(
|
||||||
`${this.baseUrl}/account/${this.userName}/image/${deleteHash}`,
|
`${this.baseUrl}/account/${this.userName}/image/${deleteHash}`,
|
||||||
@@ -166,7 +166,7 @@ class ImgurApi {
|
|||||||
* 上传文件
|
* 上传文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async uploadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async uploadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { fileArray } = configMap
|
const { fileArray } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
fileArray.forEach((item: any) => {
|
fileArray.forEach((item: any) => {
|
||||||
@@ -226,7 +226,7 @@ class ImgurApi {
|
|||||||
* 下载文件
|
* 下载文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async downloadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async downloadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
const promises = [] as any
|
const promises = [] as any
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class LocalApi {
|
|||||||
logger: ManageLogger
|
logger: ManageLogger
|
||||||
isWindows: boolean
|
isWindows: boolean
|
||||||
|
|
||||||
constructor (logger: ManageLogger) {
|
constructor(logger: ManageLogger) {
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
this.isWindows = process.platform === 'win32'
|
this.isWindows = process.platform === 'win32'
|
||||||
}
|
}
|
||||||
@@ -25,12 +25,12 @@ class LocalApi {
|
|||||||
logParam = (error: any, method: string) => this.logger.error(formatError(error, { class: 'LocalApi', method }))
|
logParam = (error: any, method: string) => this.logger.error(formatError(error, { class: 'LocalApi', method }))
|
||||||
|
|
||||||
// windows 系统下将路径转换为 unix 风格
|
// windows 系统下将路径转换为 unix 风格
|
||||||
transPathToUnix (filePath: string | undefined) {
|
transPathToUnix(filePath: string | undefined) {
|
||||||
if (!filePath) return ''
|
if (!filePath) return ''
|
||||||
return this.isWindows ? filePath.split(path.sep).join(path.posix.sep) : filePath.replace(/^\/+/, '')
|
return this.isWindows ? filePath.split(path.sep).join(path.posix.sep) : filePath.replace(/^\/+/, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
transBack (filePath: string | undefined) {
|
transBack(filePath: string | undefined) {
|
||||||
if (!filePath) return ''
|
if (!filePath) return ''
|
||||||
return this.isWindows
|
return this.isWindows
|
||||||
? filePath
|
? filePath
|
||||||
@@ -40,7 +40,7 @@ class LocalApi {
|
|||||||
: `/${filePath.replace(/^\/+|\/+$/g, '')}`
|
: `/${filePath.replace(/^\/+|\/+$/g, '')}`
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFolder (item: fs.Stats, urlPrefix: string, fileName: string, filePath: string) {
|
formatFolder(item: fs.Stats, urlPrefix: string, fileName: string, filePath: string) {
|
||||||
const key = `${this.transPathToUnix(filePath)}/`.replace(/\/+$/, '/')
|
const key = `${this.transPathToUnix(filePath)}/`.replace(/\/+$/, '/')
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
@@ -57,7 +57,7 @@ class LocalApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFile (item: fs.Stats, urlPrefix: string, fileName: string, filePath: string, isDownload = false) {
|
formatFile(item: fs.Stats, urlPrefix: string, fileName: string, filePath: string, isDownload = false) {
|
||||||
const key = isDownload ? filePath : this.transPathToUnix(filePath)
|
const key = isDownload ? filePath : this.transPathToUnix(filePath)
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
@@ -74,7 +74,7 @@ class LocalApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListRecursively(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { prefix, customUrl = '', cancelToken } = configMap
|
const { prefix, customUrl = '', cancelToken } = configMap
|
||||||
const urlPrefix = customUrl.replace(/\/+$/, '')
|
const urlPrefix = customUrl.replace(/\/+$/, '')
|
||||||
@@ -114,7 +114,7 @@ class LocalApi {
|
|||||||
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { customUrl = '', cancelToken, baseDir } = configMap
|
const { customUrl = '', cancelToken, baseDir } = configMap
|
||||||
let prefix = configMap.prefix
|
let prefix = configMap.prefix
|
||||||
@@ -170,7 +170,7 @@ class LocalApi {
|
|||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
}
|
}
|
||||||
|
|
||||||
async renameBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async renameBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { oldKey, newKey } = configMap
|
const { oldKey, newKey } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
@@ -182,7 +182,7 @@ class LocalApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
@@ -194,7 +194,7 @@ class LocalApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
@@ -208,7 +208,7 @@ class LocalApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async uploadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async uploadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { fileArray } = configMap
|
const { fileArray } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
for (const item of fileArray) {
|
for (const item of fileArray) {
|
||||||
@@ -250,7 +250,7 @@ class LocalApi {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
async createBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async createBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
@@ -264,7 +264,7 @@ class LocalApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async downloadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { downloadPath, fileArray } = configMap
|
const { downloadPath, fileArray } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
for (const item of fileArray) {
|
for (const item of fileArray) {
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ class QiniuApi {
|
|||||||
getBucketDomain: 'https://uc.qiniuapi.com/v2/domains'
|
getBucketDomain: 'https://uc.qiniuapi.com/v2/domains'
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor (accessKey: string, secretKey: string, logger: ManageLogger) {
|
constructor(accessKey: string, secretKey: string, logger: ManageLogger) {
|
||||||
this.mac = new qiniu.auth.digest.Mac(accessKey, secretKey)
|
this.mac = new qiniu.auth.digest.Mac(accessKey, secretKey)
|
||||||
this.accessKey = accessKey
|
this.accessKey = accessKey
|
||||||
this.secretKey = secretKey
|
this.secretKey = secretKey
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFolder (item: string, slicedPrefix: string, urlPrefix: string) {
|
formatFolder(item: string, slicedPrefix: string, urlPrefix: string) {
|
||||||
return {
|
return {
|
||||||
Key: item,
|
Key: item,
|
||||||
key: item,
|
key: item,
|
||||||
@@ -54,7 +54,7 @@ class QiniuApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFile (item: any, slicedPrefix: string, urlPrefix: string) {
|
formatFile(item: any, slicedPrefix: string, urlPrefix: string) {
|
||||||
const fileName = item.key.replace(slicedPrefix, '')
|
const fileName = item.key.replace(slicedPrefix, '')
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
@@ -69,7 +69,7 @@ class QiniuApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
authorization (
|
authorization(
|
||||||
method: string,
|
method: string,
|
||||||
urlPath: string,
|
urlPath: string,
|
||||||
host: string,
|
host: string,
|
||||||
@@ -98,7 +98,7 @@ class QiniuApi {
|
|||||||
/**
|
/**
|
||||||
* 获取存储桶列表
|
* 获取存储桶列表
|
||||||
*/
|
*/
|
||||||
async getBucketList (): Promise<any> {
|
async getBucketList(): Promise<any> {
|
||||||
const host = this.hostList.getBucketList
|
const host = this.hostList.getBucketList
|
||||||
const authorization = qiniu.util.generateAccessToken(this.mac, host, undefined)
|
const authorization = qiniu.util.generateAccessToken(this.mac, host, undefined)
|
||||||
const res = await axios.get(host, {
|
const res = await axios.get(host, {
|
||||||
@@ -128,7 +128,7 @@ class QiniuApi {
|
|||||||
/**
|
/**
|
||||||
* 获取存储桶详细信息
|
* 获取存储桶详细信息
|
||||||
*/
|
*/
|
||||||
async getBucketInfo (param: IStringKeyMap): Promise<any> {
|
async getBucketInfo(param: IStringKeyMap): Promise<any> {
|
||||||
const { bucketName } = param
|
const { bucketName } = param
|
||||||
const urlPath = `/v2/bucketInfo?bucket=${bucketName}&fs=true`
|
const urlPath = `/v2/bucketInfo?bucket=${bucketName}&fs=true`
|
||||||
const authorization = this.authorization('POST', urlPath, this.host, '', '', 'application/json')
|
const authorization = this.authorization('POST', urlPath, this.host, '', '', 'application/json')
|
||||||
@@ -160,7 +160,7 @@ class QiniuApi {
|
|||||||
/**
|
/**
|
||||||
* 获取自定义域名
|
* 获取自定义域名
|
||||||
*/
|
*/
|
||||||
async getBucketDomain (param: IStringKeyMap): Promise<any> {
|
async getBucketDomain(param: IStringKeyMap): Promise<any> {
|
||||||
const { bucketName } = param
|
const { bucketName } = param
|
||||||
const host = this.hostList.getBucketDomain
|
const host = this.hostList.getBucketDomain
|
||||||
const authorization = qiniu.util.generateAccessToken(this.mac, `${host}?tbl=${bucketName}`, undefined)
|
const authorization = qiniu.util.generateAccessToken(this.mac, `${host}?tbl=${bucketName}`, undefined)
|
||||||
@@ -180,7 +180,7 @@ class QiniuApi {
|
|||||||
/**
|
/**
|
||||||
* 修改存储桶权限
|
* 修改存储桶权限
|
||||||
*/
|
*/
|
||||||
async setBucketAclPolicy (param: IStringKeyMap): Promise<boolean> {
|
async setBucketAclPolicy(param: IStringKeyMap): Promise<boolean> {
|
||||||
// 0: 公开访问 1: 私有访问
|
// 0: 公开访问 1: 私有访问
|
||||||
const { bucketName } = param
|
const { bucketName } = param
|
||||||
let { isPrivate } = param
|
let { isPrivate } = param
|
||||||
@@ -213,7 +213,7 @@ class QiniuApi {
|
|||||||
* acl: boolean // 是否公开访问
|
* acl: boolean // 是否公开访问
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async createBucket (configMap: IStringKeyMap): Promise<boolean> {
|
async createBucket(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { BucketName, region, acl } = configMap
|
const { BucketName, region, acl } = configMap
|
||||||
const urlPath = `/mkbucketv3/${BucketName}/region/${region}`
|
const urlPath = `/mkbucketv3/${BucketName}/region/${region}`
|
||||||
const authorization = this.authorization('POST', urlPath, this.host, '', '', 'application/json')
|
const authorization = this.authorization('POST', urlPath, this.host, '', '', 'application/json')
|
||||||
@@ -235,7 +235,7 @@ class QiniuApi {
|
|||||||
: false
|
: false
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListRecursively(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { bucketName: bucket, prefix, cancelToken, customUrl: urlPrefix } = configMap
|
const { bucketName: bucket, prefix, cancelToken, customUrl: urlPrefix } = configMap
|
||||||
let marker = undefined as any
|
let marker = undefined as any
|
||||||
@@ -297,7 +297,7 @@ class QiniuApi {
|
|||||||
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { bucketName: bucket, prefix, cancelToken, customUrl: urlPrefix } = configMap
|
const { bucketName: bucket, prefix, cancelToken, customUrl: urlPrefix } = configMap
|
||||||
let marker = undefined as any
|
let marker = undefined as any
|
||||||
@@ -380,7 +380,7 @@ class QiniuApi {
|
|||||||
* customUrl: string
|
* customUrl: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async getBucketFileList (configMap: IStringKeyMap): Promise<any> {
|
async getBucketFileList(configMap: IStringKeyMap): Promise<any> {
|
||||||
const { bucketName: bucket, prefix, marker, itemsPerPage, customUrl: urlPrefix } = configMap
|
const { bucketName: bucket, prefix, marker, itemsPerPage, customUrl: urlPrefix } = configMap
|
||||||
const slicedPrefix = prefix.slice(1)
|
const slicedPrefix = prefix.slice(1)
|
||||||
const config = new qiniu.conf.Config()
|
const config = new qiniu.conf.Config()
|
||||||
@@ -440,7 +440,7 @@ class QiniuApi {
|
|||||||
* key: string
|
* key: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async deleteBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, key } = configMap
|
const { bucketName, key } = configMap
|
||||||
const config = new qiniu.conf.Config()
|
const config = new qiniu.conf.Config()
|
||||||
const bucketManager = new qiniu.rs.BucketManager(this.mac, config)
|
const bucketManager = new qiniu.rs.BucketManager(this.mac, config)
|
||||||
@@ -463,7 +463,7 @@ class QiniuApi {
|
|||||||
* 删除文件夹
|
* 删除文件夹
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async deleteBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, key } = configMap
|
const { bucketName, key } = configMap
|
||||||
const config = new qiniu.conf.Config()
|
const config = new qiniu.conf.Config()
|
||||||
const bucketManager = new qiniu.rs.BucketManager(this.mac, config)
|
const bucketManager = new qiniu.rs.BucketManager(this.mac, config)
|
||||||
@@ -535,7 +535,7 @@ class QiniuApi {
|
|||||||
* newKey: string
|
* newKey: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async renameBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async renameBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, oldKey, newKey } = configMap
|
const { bucketName, oldKey, newKey } = configMap
|
||||||
const config = new qiniu.conf.Config()
|
const config = new qiniu.conf.Config()
|
||||||
const bucketManager = new qiniu.rs.BucketManager(this.mac, config)
|
const bucketManager = new qiniu.rs.BucketManager(this.mac, config)
|
||||||
@@ -574,7 +574,7 @@ class QiniuApi {
|
|||||||
* customUrl: string
|
* customUrl: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async getPreSignedUrl (configMap: IStringKeyMap): Promise<string> {
|
async getPreSignedUrl(configMap: IStringKeyMap): Promise<string> {
|
||||||
const { key, expires, customUrl } = configMap
|
const { key, expires, customUrl } = configMap
|
||||||
const config = new qiniu.conf.Config()
|
const config = new qiniu.conf.Config()
|
||||||
const bucketManager = new qiniu.rs.BucketManager(this.mac, config)
|
const bucketManager = new qiniu.rs.BucketManager(this.mac, config)
|
||||||
@@ -588,7 +588,7 @@ class QiniuApi {
|
|||||||
* 上传文件
|
* 上传文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async uploadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async uploadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { fileArray } = configMap
|
const { fileArray } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
fileArray.forEach((item: any) => {
|
fileArray.forEach((item: any) => {
|
||||||
@@ -667,7 +667,7 @@ class QiniuApi {
|
|||||||
* 新建文件夹
|
* 新建文件夹
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async createBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async createBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, key } = configMap
|
const { bucketName, key } = configMap
|
||||||
const putPolicy = new qiniu.rs.PutPolicy({
|
const putPolicy = new qiniu.rs.PutPolicy({
|
||||||
scope: `${bucketName}:${key}`
|
scope: `${bucketName}:${key}`
|
||||||
@@ -694,7 +694,7 @@ class QiniuApi {
|
|||||||
* 下载文件
|
* 下载文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async downloadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async downloadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
const promises = [] as any
|
const promises = [] as any
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class S3plistApi {
|
|||||||
secretAccessKey: string
|
secretAccessKey: string
|
||||||
bucketName: string
|
bucketName: string
|
||||||
|
|
||||||
constructor (
|
constructor(
|
||||||
accessKeyId: string,
|
accessKeyId: string,
|
||||||
secretAccessKey: string,
|
secretAccessKey: string,
|
||||||
endpoint: string | undefined,
|
endpoint: string | undefined,
|
||||||
@@ -75,7 +75,7 @@ class S3plistApi {
|
|||||||
this.proxy = formatHttpProxy(proxy, 'string') as string | undefined
|
this.proxy = formatHttpProxy(proxy, 'string') as string | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDogeCloudToken () {
|
async getDogeCloudToken() {
|
||||||
if (!this.dogeCloudSupport) return
|
if (!this.dogeCloudSupport) return
|
||||||
const token = (await getTempToken(this.accessKeyId, this.secretAccessKey)) as DogecloudToken
|
const token = (await getTempToken(this.accessKeyId, this.secretAccessKey)) as DogecloudToken
|
||||||
if (Object.keys(token).length === 0) {
|
if (Object.keys(token).length === 0) {
|
||||||
@@ -88,7 +88,7 @@ class S3plistApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setAgent (proxy: string | undefined, sslEnabled: boolean): NodeHttpHandler {
|
setAgent(proxy: string | undefined, sslEnabled: boolean): NodeHttpHandler {
|
||||||
const agent = getAgent(proxy, sslEnabled)
|
const agent = getAgent(proxy, sslEnabled)
|
||||||
const commonOptions: AgentOptions = {
|
const commonOptions: AgentOptions = {
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
@@ -98,26 +98,26 @@ class S3plistApi {
|
|||||||
const extraOptions = sslEnabled ? { rejectUnauthorized: false } : {}
|
const extraOptions = sslEnabled ? { rejectUnauthorized: false } : {}
|
||||||
return sslEnabled
|
return sslEnabled
|
||||||
? new NodeHttpHandler({
|
? new NodeHttpHandler({
|
||||||
httpsAgent: agent.https
|
httpsAgent: agent.https
|
||||||
? agent.https
|
? agent.https
|
||||||
: new https.Agent({
|
: new https.Agent({
|
||||||
...commonOptions,
|
...commonOptions,
|
||||||
...extraOptions
|
...extraOptions
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
: new NodeHttpHandler({
|
: new NodeHttpHandler({
|
||||||
httpAgent: agent.http
|
httpAgent: agent.http
|
||||||
? agent.http
|
? agent.http
|
||||||
: new http.Agent({
|
: new http.Agent({
|
||||||
...commonOptions,
|
...commonOptions,
|
||||||
...extraOptions
|
...extraOptions
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
logParam = (error: any, method: string) => this.logger.error(formatError(error, { class: 'S3plistApi', method }))
|
logParam = (error: any, method: string) => this.logger.error(formatError(error, { class: 'S3plistApi', method }))
|
||||||
|
|
||||||
formatFolder (item: CommonPrefix, slicedPrefix: string, urlPrefix: string): any {
|
formatFolder(item: CommonPrefix, slicedPrefix: string, urlPrefix: string): any {
|
||||||
return {
|
return {
|
||||||
Key: item.Prefix,
|
Key: item.Prefix,
|
||||||
url: `${urlPrefix}/${item.Prefix}`,
|
url: `${urlPrefix}/${item.Prefix}`,
|
||||||
@@ -132,7 +132,7 @@ class S3plistApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFile (item: _Object, slicedPrefix: string, urlPrefix: string): any {
|
formatFile(item: _Object, slicedPrefix: string, urlPrefix: string): any {
|
||||||
const fileName = item.Key?.replace(slicedPrefix, '')
|
const fileName = item.Key?.replace(slicedPrefix, '')
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
@@ -148,7 +148,7 @@ class S3plistApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async putPublicAccess (bucketName: string, client: S3Client) {
|
async putPublicAccess(bucketName: string, client: S3Client) {
|
||||||
const input = {
|
const input = {
|
||||||
Bucket: bucketName,
|
Bucket: bucketName,
|
||||||
PublicAccessBlockConfiguration: {
|
PublicAccessBlockConfiguration: {
|
||||||
@@ -175,11 +175,11 @@ class S3plistApi {
|
|||||||
* acl: string
|
* acl: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async createBucket (configMap: IStringKeyMap): Promise<boolean> {
|
async createBucket(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { BucketName, region, acl, endpoint } = configMap
|
const { BucketName, region, acl, endpoint } = configMap
|
||||||
try {
|
try {
|
||||||
await this.getDogeCloudToken()
|
await this.getDogeCloudToken()
|
||||||
const options = ({ ...this.baseOptions }) as S3ClientConfig
|
const options = { ...this.baseOptions } as S3ClientConfig
|
||||||
options.region = String(region) || 'us-east-1'
|
options.region = String(region) || 'us-east-1'
|
||||||
const client = new S3Client(options)
|
const client = new S3Client(options)
|
||||||
const command = new ListBucketsCommand({})
|
const command = new ListBucketsCommand({})
|
||||||
@@ -234,7 +234,7 @@ class S3plistApi {
|
|||||||
/**
|
/**
|
||||||
* 获取存储桶列表
|
* 获取存储桶列表
|
||||||
*/
|
*/
|
||||||
async getBucketList (): Promise<any> {
|
async getBucketList(): Promise<any> {
|
||||||
if (this.dogeCloudSupport) {
|
if (this.dogeCloudSupport) {
|
||||||
try {
|
try {
|
||||||
const res = await dogecloudApi('/oss/bucket/list.json', {}, false, this.accessKeyId, this.secretAccessKey)
|
const res = await dogecloudApi('/oss/bucket/list.json', {}, false, this.accessKeyId, this.secretAccessKey)
|
||||||
@@ -255,7 +255,7 @@ class S3plistApi {
|
|||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
const options = ({ ...this.baseOptions }) as S3ClientConfig
|
const options = { ...this.baseOptions } as S3ClientConfig
|
||||||
const result: IStringKeyMap[] = []
|
const result: IStringKeyMap[] = []
|
||||||
const endpoint = (options.endpoint as string) || ''
|
const endpoint = (options.endpoint as string) || ''
|
||||||
options.region = endpoint.includes('cloudflarestorage') ? 'auto' : 'us-east-1'
|
options.region = endpoint.includes('cloudflarestorage') ? 'auto' : 'us-east-1'
|
||||||
@@ -305,7 +305,7 @@ class S3plistApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListRecursively(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const {
|
const {
|
||||||
bucketName: bucket,
|
bucketName: bucket,
|
||||||
@@ -331,7 +331,7 @@ class S3plistApi {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
do {
|
do {
|
||||||
const options = ({ ...this.baseOptions }) as S3ClientConfig
|
const options = { ...this.baseOptions } as S3ClientConfig
|
||||||
options.region = String(region) || 'us-east-1'
|
options.region = String(region) || 'us-east-1'
|
||||||
const client = new S3Client(options)
|
const client = new S3Client(options)
|
||||||
const command = new ListObjectsV2Command({
|
const command = new ListObjectsV2Command({
|
||||||
@@ -369,7 +369,7 @@ class S3plistApi {
|
|||||||
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const {
|
const {
|
||||||
bucketName: bucket,
|
bucketName: bucket,
|
||||||
@@ -396,7 +396,7 @@ class S3plistApi {
|
|||||||
try {
|
try {
|
||||||
await this.getDogeCloudToken()
|
await this.getDogeCloudToken()
|
||||||
do {
|
do {
|
||||||
const options = ({ ...this.baseOptions }) as S3ClientConfig
|
const options = { ...this.baseOptions } as S3ClientConfig
|
||||||
options.region = String(region) || 'us-east-1'
|
options.region = String(region) || 'us-east-1'
|
||||||
const client = new S3Client(options)
|
const client = new S3Client(options)
|
||||||
const command = new ListObjectsV2Command({
|
const command = new ListObjectsV2Command({
|
||||||
@@ -439,7 +439,7 @@ class S3plistApi {
|
|||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketFileList (configMap: IStringKeyMap): Promise<any> {
|
async getBucketFileList(configMap: IStringKeyMap): Promise<any> {
|
||||||
const {
|
const {
|
||||||
bucketName: bucket,
|
bucketName: bucket,
|
||||||
bucketConfig: { Location: region },
|
bucketConfig: { Location: region },
|
||||||
@@ -457,10 +457,10 @@ class S3plistApi {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await this.getDogeCloudToken()
|
await this.getDogeCloudToken()
|
||||||
const options = ({
|
const options = {
|
||||||
|
...this.baseOptions,
|
||||||
...this.baseOptions, region: String(region) || 'us-east-1'
|
region: String(region) || 'us-east-1'
|
||||||
}) as S3ClientConfig
|
} as S3ClientConfig
|
||||||
const client = new S3Client(options)
|
const client = new S3Client(options)
|
||||||
const command = new ListObjectsV2Command({
|
const command = new ListObjectsV2Command({
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
@@ -495,15 +495,15 @@ class S3plistApi {
|
|||||||
* newKey: string
|
* newKey: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async renameBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async renameBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, region, oldKey, newKey } = configMap
|
const { bucketName, region, oldKey, newKey } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
await this.getDogeCloudToken()
|
await this.getDogeCloudToken()
|
||||||
const options = ({
|
const options = {
|
||||||
|
...this.baseOptions,
|
||||||
...this.baseOptions, region: String(region) || 'us-east-1'
|
region: String(region) || 'us-east-1'
|
||||||
}) as S3ClientConfig
|
} as S3ClientConfig
|
||||||
const client = new S3Client(options)
|
const client = new S3Client(options)
|
||||||
const command = new CopyObjectCommand({
|
const command = new CopyObjectCommand({
|
||||||
Bucket: bucketName,
|
Bucket: bucketName,
|
||||||
@@ -540,12 +540,12 @@ class S3plistApi {
|
|||||||
* key: string
|
* key: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async deleteBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, region, key } = configMap
|
const { bucketName, region, key } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
await this.getDogeCloudToken()
|
await this.getDogeCloudToken()
|
||||||
const options = ({ ...this.baseOptions }) as S3ClientConfig
|
const options = { ...this.baseOptions } as S3ClientConfig
|
||||||
options.region = String(region) || 'us-east-1'
|
options.region = String(region) || 'us-east-1'
|
||||||
const client = new S3Client(options)
|
const client = new S3Client(options)
|
||||||
const command = new DeleteObjectCommand({
|
const command = new DeleteObjectCommand({
|
||||||
@@ -568,7 +568,7 @@ class S3plistApi {
|
|||||||
* 删除文件夹
|
* 删除文件夹
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async deleteBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, region, key } = configMap
|
const { bucketName, region, key } = configMap
|
||||||
let marker
|
let marker
|
||||||
let result = false
|
let result = false
|
||||||
@@ -581,7 +581,7 @@ class S3plistApi {
|
|||||||
try {
|
try {
|
||||||
await this.getDogeCloudToken()
|
await this.getDogeCloudToken()
|
||||||
do {
|
do {
|
||||||
const options = ({ ...this.baseOptions }) as S3ClientConfig
|
const options = { ...this.baseOptions } as S3ClientConfig
|
||||||
options.region = String(region) || 'us-east-1'
|
options.region = String(region) || 'us-east-1'
|
||||||
const client = new S3Client(options)
|
const client = new S3Client(options)
|
||||||
const command = new ListObjectsV2Command({
|
const command = new ListObjectsV2Command({
|
||||||
@@ -616,7 +616,7 @@ class S3plistApi {
|
|||||||
}
|
}
|
||||||
if (allFileList.Contents.length > 0) {
|
if (allFileList.Contents.length > 0) {
|
||||||
const cycle = Math.ceil(allFileList.Contents.length / 1000)
|
const cycle = Math.ceil(allFileList.Contents.length / 1000)
|
||||||
const options = ({ ...this.baseOptions }) as S3ClientConfig
|
const options = { ...this.baseOptions } as S3ClientConfig
|
||||||
options.region = String(region) || 'us-east-1'
|
options.region = String(region) || 'us-east-1'
|
||||||
const client = new S3Client(options)
|
const client = new S3Client(options)
|
||||||
for (let i = 0; i < cycle; i++) {
|
for (let i = 0; i < cycle; i++) {
|
||||||
@@ -657,11 +657,11 @@ class S3plistApi {
|
|||||||
* customUrl: string
|
* customUrl: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async getPreSignedUrl (configMap: IStringKeyMap): Promise<string> {
|
async getPreSignedUrl(configMap: IStringKeyMap): Promise<string> {
|
||||||
const { bucketName, region, key, expires } = configMap
|
const { bucketName, region, key, expires } = configMap
|
||||||
try {
|
try {
|
||||||
await this.getDogeCloudToken()
|
await this.getDogeCloudToken()
|
||||||
const options = ({ ...this.baseOptions }) as S3ClientConfig
|
const options = { ...this.baseOptions } as S3ClientConfig
|
||||||
options.region = String(region) || 'us-east-1'
|
options.region = String(region) || 'us-east-1'
|
||||||
const client = new S3Client(options)
|
const client = new S3Client(options)
|
||||||
const signedUrl = await getSignedUrl(
|
const signedUrl = await getSignedUrl(
|
||||||
@@ -685,12 +685,12 @@ class S3plistApi {
|
|||||||
* 新建文件夹
|
* 新建文件夹
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async createBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async createBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, region, key } = configMap
|
const { bucketName, region, key } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
await this.getDogeCloudToken()
|
await this.getDogeCloudToken()
|
||||||
const options = ({ ...this.baseOptions }) as S3ClientConfig
|
const options = { ...this.baseOptions } as S3ClientConfig
|
||||||
options.region = String(region) || 'us-east-1'
|
options.region = String(region) || 'us-east-1'
|
||||||
const client = new S3Client(options)
|
const client = new S3Client(options)
|
||||||
const command = new PutObjectCommand({
|
const command = new PutObjectCommand({
|
||||||
@@ -713,7 +713,7 @@ class S3plistApi {
|
|||||||
* upload file
|
* upload file
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async uploadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async uploadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { fileArray } = configMap
|
const { fileArray } = configMap
|
||||||
// fileArray = [{
|
// fileArray = [{
|
||||||
// bucketName: string,
|
// bucketName: string,
|
||||||
@@ -764,7 +764,7 @@ class S3plistApi {
|
|||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const options = ({ ...this.baseOptions }) as S3ClientConfig
|
const options = { ...this.baseOptions } as S3ClientConfig
|
||||||
options.region = String(region) || 'us-east-1'
|
options.region = String(region) || 'us-east-1'
|
||||||
const client = new S3Client(options)
|
const client = new S3Client(options)
|
||||||
const fileStream = fs.createReadStream(filePath)
|
const fileStream = fs.createReadStream(filePath)
|
||||||
@@ -825,7 +825,7 @@ class S3plistApi {
|
|||||||
* 下载文件
|
* 下载文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async downloadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async downloadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
const promises = [] as any
|
const promises = [] as any
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class SftpApi {
|
|||||||
passphrase: string
|
passphrase: string
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor (
|
constructor(
|
||||||
host: string,
|
host: string,
|
||||||
port: Undefinable<number>,
|
port: Undefinable<number>,
|
||||||
username: Undefinable<string>,
|
username: Undefinable<string>,
|
||||||
@@ -94,7 +94,7 @@ class SftpApi {
|
|||||||
return `0${result}`
|
return `0${result}`
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFolder (item: listDirResult, urlPrefix: string, isWebPath = false) {
|
formatFolder(item: listDirResult, urlPrefix: string, isWebPath = false) {
|
||||||
const key = item.key
|
const key = item.key
|
||||||
let url: string
|
let url: string
|
||||||
if (isWebPath) {
|
if (isWebPath) {
|
||||||
@@ -121,7 +121,7 @@ class SftpApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFile (item: listDirResult, urlPrefix: string, isWebPath = false) {
|
formatFile(item: listDirResult, urlPrefix: string, isWebPath = false) {
|
||||||
const key = item.key
|
const key = item.key
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
@@ -151,7 +151,7 @@ class SftpApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListRecursively(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { prefix, customUrl, cancelToken } = configMap
|
const { prefix, customUrl, cancelToken } = configMap
|
||||||
const urlPrefix = customUrl || `${this.host}:${this.port}`
|
const urlPrefix = customUrl || `${this.host}:${this.port}`
|
||||||
@@ -191,7 +191,7 @@ class SftpApi {
|
|||||||
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
}
|
}
|
||||||
|
|
||||||
formatLSResult (res: string, cwd: string): listDirResult[] {
|
formatLSResult(res: string, cwd: string): listDirResult[] {
|
||||||
const result = [] as listDirResult[]
|
const result = [] as listDirResult[]
|
||||||
const resArray = res.trim().split('\n')
|
const resArray = res.trim().split('\n')
|
||||||
resArray.slice(resArray[0].startsWith('total') ? 1 : 0).forEach((item: string) => {
|
resArray.slice(resArray[0].startsWith('total') ? 1 : 0).forEach((item: string) => {
|
||||||
@@ -217,7 +217,7 @@ class SftpApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { prefix, customUrl, cancelToken, baseDir } = configMap
|
const { prefix, customUrl, cancelToken, baseDir } = configMap
|
||||||
let urlPrefix = customUrl || `${this.host}:${this.port}`
|
let urlPrefix = customUrl || `${this.host}:${this.port}`
|
||||||
@@ -276,7 +276,7 @@ class SftpApi {
|
|||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
}
|
}
|
||||||
|
|
||||||
async renameBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async renameBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { oldKey, newKey } = configMap
|
const { oldKey, newKey } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
@@ -290,7 +290,7 @@ class SftpApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
@@ -304,7 +304,7 @@ class SftpApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
@@ -321,7 +321,7 @@ class SftpApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async uploadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async uploadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { fileArray } = configMap
|
const { fileArray } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
for (const item of fileArray) {
|
for (const item of fileArray) {
|
||||||
@@ -376,7 +376,7 @@ class SftpApi {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
async createBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async createBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
@@ -390,7 +390,7 @@ class SftpApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async downloadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { downloadPath, fileArray } = configMap
|
const { downloadPath, fileArray } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
for (const item of fileArray) {
|
for (const item of fileArray) {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class SmmsApi {
|
|||||||
logger: ManageLogger
|
logger: ManageLogger
|
||||||
timeout = 30000
|
timeout = 30000
|
||||||
|
|
||||||
constructor (token: string, logger: ManageLogger) {
|
constructor(token: string, logger: ManageLogger) {
|
||||||
this.token = token
|
this.token = token
|
||||||
this.axiosInstance = axios.create({
|
this.axiosInstance = axios.create({
|
||||||
baseURL: this.baseUrl,
|
baseURL: this.baseUrl,
|
||||||
@@ -37,7 +37,7 @@ class SmmsApi {
|
|||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFile (item: any) {
|
formatFile(item: any) {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
Key: item.path,
|
Key: item.path,
|
||||||
@@ -54,7 +54,7 @@ class SmmsApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { cancelToken } = configMap
|
const { cancelToken } = configMap
|
||||||
let marker = 1
|
let marker = 1
|
||||||
@@ -123,7 +123,7 @@ class SmmsApi {
|
|||||||
* customUrl: string
|
* customUrl: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async getBucketFileList ({ currentPage }: IStringKeyMap): Promise<any> {
|
async getBucketFileList({ currentPage }: IStringKeyMap): Promise<any> {
|
||||||
const result = {
|
const result = {
|
||||||
fullList: [] as any,
|
fullList: [] as any,
|
||||||
isTruncated: false,
|
isTruncated: false,
|
||||||
@@ -162,7 +162,7 @@ class SmmsApi {
|
|||||||
* DeleteHash: string
|
* DeleteHash: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async deleteBucketFile ({ DeleteHash }: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFile({ DeleteHash }: IStringKeyMap): Promise<boolean> {
|
||||||
const res = await this.axiosInstance(`/delete/${DeleteHash}`, {
|
const res = await this.axiosInstance(`/delete/${DeleteHash}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
params: {
|
params: {
|
||||||
@@ -177,7 +177,7 @@ class SmmsApi {
|
|||||||
* 上传文件
|
* 上传文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async uploadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async uploadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { fileArray } = configMap
|
const { fileArray } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
for (const item of fileArray) {
|
for (const item of fileArray) {
|
||||||
@@ -214,7 +214,7 @@ class SmmsApi {
|
|||||||
* 下载文件
|
* 下载文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async downloadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async downloadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
const promises = [] as any
|
const promises = [] as any
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class TcyunApi {
|
|||||||
ctx: COS
|
ctx: COS
|
||||||
logger: ManageLogger
|
logger: ManageLogger
|
||||||
|
|
||||||
constructor (secretId: string, secretKey: string, logger: ManageLogger) {
|
constructor(secretId: string, secretKey: string, logger: ManageLogger) {
|
||||||
this.ctx = new COS({
|
this.ctx = new COS({
|
||||||
SecretId: secretId,
|
SecretId: secretId,
|
||||||
SecretKey: secretKey
|
SecretKey: secretKey
|
||||||
@@ -25,7 +25,7 @@ class TcyunApi {
|
|||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFolder (item: { Prefix: string }, slicedPrefix: string, urlPrefix: string) {
|
formatFolder(item: { Prefix: string }, slicedPrefix: string, urlPrefix: string) {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
key: item.Prefix,
|
key: item.Prefix,
|
||||||
@@ -40,7 +40,7 @@ class TcyunApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFile (item: COS.CosObject, slicedPrefix: string, urlPrefix: string): any {
|
formatFile(item: COS.CosObject, slicedPrefix: string, urlPrefix: string): any {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
key: item.Key,
|
key: item.Key,
|
||||||
@@ -58,7 +58,7 @@ class TcyunApi {
|
|||||||
/**
|
/**
|
||||||
* 获取存储桶列表
|
* 获取存储桶列表
|
||||||
*/
|
*/
|
||||||
async getBucketList (): Promise<any> {
|
async getBucketList(): Promise<any> {
|
||||||
const res = await this.ctx.getService({})
|
const res = await this.ctx.getService({})
|
||||||
return res?.Buckets || []
|
return res?.Buckets || []
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ class TcyunApi {
|
|||||||
/**
|
/**
|
||||||
* 获取自定义域名
|
* 获取自定义域名
|
||||||
*/
|
*/
|
||||||
async getBucketDomain (param: IStringKeyMap): Promise<any> {
|
async getBucketDomain(param: IStringKeyMap): Promise<any> {
|
||||||
const { bucketName, region } = param
|
const { bucketName, region } = param
|
||||||
const res = await this.ctx.getBucketDomain({
|
const res = await this.ctx.getBucketDomain({
|
||||||
Bucket: bucketName,
|
Bucket: bucketName,
|
||||||
@@ -87,7 +87,7 @@ class TcyunApi {
|
|||||||
* @description
|
* @description
|
||||||
* acl: private | publicRead | publicReadWrite
|
* acl: private | publicRead | publicReadWrite
|
||||||
*/
|
*/
|
||||||
async createBucket (configMap: IStringKeyMap): Promise<boolean> {
|
async createBucket(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const res = await this.ctx.putBucket({
|
const res = await this.ctx.putBucket({
|
||||||
ACL: configMap.acl,
|
ACL: configMap.acl,
|
||||||
Bucket: configMap.BucketName,
|
Bucket: configMap.BucketName,
|
||||||
@@ -96,7 +96,7 @@ class TcyunApi {
|
|||||||
return res?.statusCode === 200
|
return res?.statusCode === 200
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListRecursively(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const {
|
const {
|
||||||
bucketName: bucket,
|
bucketName: bucket,
|
||||||
@@ -150,7 +150,7 @@ class TcyunApi {
|
|||||||
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const {
|
const {
|
||||||
bucketName: bucket,
|
bucketName: bucket,
|
||||||
@@ -221,7 +221,7 @@ class TcyunApi {
|
|||||||
* customUrl: string
|
* customUrl: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async getBucketFileList (configMap: IStringKeyMap): Promise<any> {
|
async getBucketFileList(configMap: IStringKeyMap): Promise<any> {
|
||||||
const {
|
const {
|
||||||
bucketName: bucket,
|
bucketName: bucket,
|
||||||
bucketConfig: { Location: region },
|
bucketConfig: { Location: region },
|
||||||
@@ -272,7 +272,7 @@ class TcyunApi {
|
|||||||
* newKey: string
|
* newKey: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async renameBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async renameBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, region, oldKey, newKey } = configMap
|
const { bucketName, region, oldKey, newKey } = configMap
|
||||||
const copyRes = await this.ctx.putObjectCopy({
|
const copyRes = await this.ctx.putObjectCopy({
|
||||||
Bucket: bucketName,
|
Bucket: bucketName,
|
||||||
@@ -301,7 +301,7 @@ class TcyunApi {
|
|||||||
* key: string
|
* key: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async deleteBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, region, key } = configMap
|
const { bucketName, region, key } = configMap
|
||||||
const res = await this.ctx.deleteObject({
|
const res = await this.ctx.deleteObject({
|
||||||
Bucket: bucketName,
|
Bucket: bucketName,
|
||||||
@@ -315,7 +315,7 @@ class TcyunApi {
|
|||||||
* 删除文件夹
|
* 删除文件夹
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async deleteBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, region, key } = configMap
|
const { bucketName, region, key } = configMap
|
||||||
let marker
|
let marker
|
||||||
let res: any
|
let res: any
|
||||||
@@ -346,7 +346,9 @@ class TcyunApi {
|
|||||||
region,
|
region,
|
||||||
key: item.Prefix
|
key: item.Prefix
|
||||||
}))
|
}))
|
||||||
) { return false }
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const cycles = Math.ceil(allFileList.Contents.length / 1000)
|
const cycles = Math.ceil(allFileList.Contents.length / 1000)
|
||||||
for (let i = 0; i < cycles; i++) {
|
for (let i = 0; i < cycles; i++) {
|
||||||
@@ -371,7 +373,7 @@ class TcyunApi {
|
|||||||
* customUrl: string
|
* customUrl: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async getPreSignedUrl (configMap: IStringKeyMap): Promise<string> {
|
async getPreSignedUrl(configMap: IStringKeyMap): Promise<string> {
|
||||||
const { bucketName, region, key, expires, customUrl } = configMap
|
const { bucketName, region, key, expires, customUrl } = configMap
|
||||||
const res = this.ctx.getObjectUrl(
|
const res = this.ctx.getObjectUrl(
|
||||||
{
|
{
|
||||||
@@ -390,7 +392,7 @@ class TcyunApi {
|
|||||||
* 高级上传文件
|
* 高级上传文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async uploadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async uploadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { fileArray } = configMap
|
const { fileArray } = configMap
|
||||||
// fileArray = [{
|
// fileArray = [{
|
||||||
// bucketName: string,
|
// bucketName: string,
|
||||||
@@ -470,7 +472,7 @@ class TcyunApi {
|
|||||||
* 新建文件夹
|
* 新建文件夹
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async createBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async createBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { bucketName, region, key } = configMap
|
const { bucketName, region, key } = configMap
|
||||||
const res = await this.ctx.putObject({
|
const res = await this.ctx.putObject({
|
||||||
Bucket: bucketName,
|
Bucket: bucketName,
|
||||||
@@ -485,7 +487,7 @@ class TcyunApi {
|
|||||||
* 下载文件
|
* 下载文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async downloadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async downloadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { downloadPath, fileArray } = configMap
|
const { downloadPath, fileArray } = configMap
|
||||||
// fileArray = [{
|
// fileArray = [{
|
||||||
// bucketName: string,
|
// bucketName: string,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class UpyunApi {
|
|||||||
stopMarker = 'g2gCZAAEbmV4dGQAA2VvZg'
|
stopMarker = 'g2gCZAAEbmV4dGQAA2VvZg'
|
||||||
logger: ManageLogger
|
logger: ManageLogger
|
||||||
|
|
||||||
constructor (
|
constructor(
|
||||||
bucket: string,
|
bucket: string,
|
||||||
operator: string,
|
operator: string,
|
||||||
password: string,
|
password: string,
|
||||||
@@ -52,7 +52,7 @@ class UpyunApi {
|
|||||||
this.expireTime = expireTime || 24 * 60 * 60
|
this.expireTime = expireTime || 24 * 60 * 60
|
||||||
}
|
}
|
||||||
|
|
||||||
getAntiLeechParam (key: string): string {
|
getAntiLeechParam(key: string): string {
|
||||||
const uri = `/${key}`.replace(/%2F/g, '/').replace(/^\/+/g, '/')
|
const uri = `/${key}`.replace(/%2F/g, '/').replace(/^\/+/g, '/')
|
||||||
const now = Math.round(new Date().getTime() / 1000)
|
const now = Math.round(new Date().getTime() / 1000)
|
||||||
const expire = this.expireTime ? now + parseInt(this.expireTime.toString(), 10) : now + 1800
|
const expire = this.expireTime ? now + parseInt(this.expireTime.toString(), 10) : now + 1800
|
||||||
@@ -61,7 +61,7 @@ class UpyunApi {
|
|||||||
return `_upt=${upt}`
|
return `_upt=${upt}`
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFolder (item: any, slicedPrefix: string, urlPrefix: string) {
|
formatFolder(item: any, slicedPrefix: string, urlPrefix: string) {
|
||||||
const key = `${slicedPrefix}${item.name}/`
|
const key = `${slicedPrefix}${item.name}/`
|
||||||
let url = `${urlPrefix}/${key}`
|
let url = `${urlPrefix}/${key}`
|
||||||
if (this.antiLeechToken) {
|
if (this.antiLeechToken) {
|
||||||
@@ -82,7 +82,7 @@ class UpyunApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFile (item: any, slicedPrefix: string, urlPrefix: string) {
|
formatFile(item: any, slicedPrefix: string, urlPrefix: string) {
|
||||||
const key = `${slicedPrefix}${item.name}`
|
const key = `${slicedPrefix}${item.name}`
|
||||||
let url = `${urlPrefix}/${key}`
|
let url = `${urlPrefix}/${key}`
|
||||||
if (this.antiLeechToken) {
|
if (this.antiLeechToken) {
|
||||||
@@ -102,7 +102,7 @@ class UpyunApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
authorization (method: string, uri: string, contentMd5: string, operator: string, password: string) {
|
authorization(method: string, uri: string, contentMd5: string, operator: string, password: string) {
|
||||||
return `UPYUN ${operator}:${hmacSha1Base64(
|
return `UPYUN ${operator}:${hmacSha1Base64(
|
||||||
md5(password, 'hex'),
|
md5(password, 'hex'),
|
||||||
`${method.toUpperCase()}&${encodeURI(uri)}&${new Date().toUTCString()}${contentMd5 ? `&${contentMd5}` : ''}`
|
`${method.toUpperCase()}&${encodeURI(uri)}&${new Date().toUTCString()}${contentMd5 ? `&${contentMd5}` : ''}`
|
||||||
@@ -112,11 +112,11 @@ class UpyunApi {
|
|||||||
/**
|
/**
|
||||||
* 获取空间列表
|
* 获取空间列表
|
||||||
*/
|
*/
|
||||||
async getBucketList (): Promise<any> {
|
async getBucketList(): Promise<any> {
|
||||||
return this.bucket
|
return this.bucket
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListRecursively(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { bucketName: bucket, prefix, cancelToken } = configMap
|
const { bucketName: bucket, prefix, cancelToken } = configMap
|
||||||
const slicedPrefix = prefix.slice(1)
|
const slicedPrefix = prefix.slice(1)
|
||||||
@@ -168,7 +168,7 @@ class UpyunApi {
|
|||||||
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { bucketName: bucket, prefix, cancelToken } = configMap
|
const { bucketName: bucket, prefix, cancelToken } = configMap
|
||||||
const slicedPrefix = prefix.slice(1)
|
const slicedPrefix = prefix.slice(1)
|
||||||
@@ -227,7 +227,7 @@ class UpyunApi {
|
|||||||
* customUrl: string
|
* customUrl: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async getBucketFileList (configMap: IStringKeyMap): Promise<any> {
|
async getBucketFileList(configMap: IStringKeyMap): Promise<any> {
|
||||||
const { bucketName: bucket, prefix, marker, itemsPerPage } = configMap
|
const { bucketName: bucket, prefix, marker, itemsPerPage } = configMap
|
||||||
const slicedPrefix = prefix.slice(1)
|
const slicedPrefix = prefix.slice(1)
|
||||||
const urlPrefix = configMap.customUrl || `http://${bucket}.test.upcdn.net`
|
const urlPrefix = configMap.customUrl || `http://${bucket}.test.upcdn.net`
|
||||||
@@ -264,7 +264,7 @@ class UpyunApi {
|
|||||||
* newKey: string
|
* newKey: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async renameBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async renameBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const oldKey = configMap.oldKey
|
const oldKey = configMap.oldKey
|
||||||
let newKey = configMap.newKey
|
let newKey = configMap.newKey
|
||||||
const method = 'PUT'
|
const method = 'PUT'
|
||||||
@@ -297,7 +297,7 @@ class UpyunApi {
|
|||||||
* key: string
|
* key: string
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
async deleteBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
const res = await this.cli.deleteFile(key)
|
const res = await this.cli.deleteFile(key)
|
||||||
return res
|
return res
|
||||||
@@ -307,7 +307,7 @@ class UpyunApi {
|
|||||||
* delete bucket folder
|
* delete bucket folder
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async deleteBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
let marker = ''
|
let marker = ''
|
||||||
let isTruncated
|
let isTruncated
|
||||||
@@ -370,7 +370,7 @@ class UpyunApi {
|
|||||||
* axiso:onUploadProgress not work in nodejs , use got instead
|
* axiso:onUploadProgress not work in nodejs , use got instead
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async uploadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async uploadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { fileArray } = configMap
|
const { fileArray } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
fileArray.forEach((item: any) => {
|
fileArray.forEach((item: any) => {
|
||||||
@@ -426,7 +426,7 @@ class UpyunApi {
|
|||||||
* 新建文件夹
|
* 新建文件夹
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async createBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async createBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
const res = await this.cli.makeDir(`/${key}`)
|
const res = await this.cli.makeDir(`/${key}`)
|
||||||
return res
|
return res
|
||||||
@@ -436,7 +436,7 @@ class UpyunApi {
|
|||||||
* 下载文件
|
* 下载文件
|
||||||
* @param configMap
|
* @param configMap
|
||||||
*/
|
*/
|
||||||
async downloadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async downloadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
const promises = [] as any
|
const promises = [] as any
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class WebdavplistApi {
|
|||||||
agent: https.Agent | http.Agent
|
agent: https.Agent | http.Agent
|
||||||
ctx: WebDAVClient
|
ctx: WebDAVClient
|
||||||
|
|
||||||
constructor (
|
constructor(
|
||||||
endpoint: string,
|
endpoint: string,
|
||||||
username: string,
|
username: string,
|
||||||
password: string,
|
password: string,
|
||||||
@@ -62,7 +62,7 @@ class WebdavplistApi {
|
|||||||
|
|
||||||
logParam = (error: any, method: string) => this.logger.error(formatError(error, { class: 'WebdavplistApi', method }))
|
logParam = (error: any, method: string) => this.logger.error(formatError(error, { class: 'WebdavplistApi', method }))
|
||||||
|
|
||||||
formatFolder (item: FileStat, urlPrefix: string, isWebPath = false) {
|
formatFolder(item: FileStat, urlPrefix: string, isWebPath = false) {
|
||||||
const key = item.filename.replace(/^\/+/, '')
|
const key = item.filename.replace(/^\/+/, '')
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
@@ -79,7 +79,7 @@ class WebdavplistApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFile (item: FileStat, urlPrefix: string, isWebPath = false) {
|
formatFile(item: FileStat, urlPrefix: string, isWebPath = false) {
|
||||||
const key = item.filename.replace(/^\/+/, '')
|
const key = item.filename.replace(/^\/+/, '')
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
@@ -98,7 +98,7 @@ class WebdavplistApi {
|
|||||||
|
|
||||||
isRequestSuccess = (code: number) => code >= 200 && code < 300
|
isRequestSuccess = (code: number) => code >= 200 && code < 300
|
||||||
|
|
||||||
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListRecursively(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { prefix, customUrl, cancelToken } = configMap
|
const { prefix, customUrl, cancelToken } = configMap
|
||||||
const urlPrefix = customUrl || this.endpoint
|
const urlPrefix = customUrl || this.endpoint
|
||||||
@@ -138,7 +138,7 @@ class WebdavplistApi {
|
|||||||
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage(configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { prefix, customUrl, cancelToken, baseDir } = configMap
|
const { prefix, customUrl, cancelToken, baseDir } = configMap
|
||||||
let urlPrefix = customUrl || this.endpoint
|
let urlPrefix = customUrl || this.endpoint
|
||||||
@@ -197,7 +197,7 @@ class WebdavplistApi {
|
|||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
}
|
}
|
||||||
|
|
||||||
async renameBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async renameBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { oldKey, newKey } = configMap
|
const { oldKey, newKey } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
@@ -209,7 +209,7 @@ class WebdavplistApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
@@ -221,7 +221,7 @@ class WebdavplistApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
@@ -233,7 +233,7 @@ class WebdavplistApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPreSignedUrl (configMap: IStringKeyMap): Promise<string> {
|
async getPreSignedUrl(configMap: IStringKeyMap): Promise<string> {
|
||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
let result = ''
|
let result = ''
|
||||||
try {
|
try {
|
||||||
@@ -245,7 +245,7 @@ class WebdavplistApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async uploadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async uploadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { fileArray } = configMap
|
const { fileArray } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
for (const item of fileArray) {
|
for (const item of fileArray) {
|
||||||
@@ -306,7 +306,7 @@ class WebdavplistApi {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
async createBucketFolder (configMap: IStringKeyMap): Promise<boolean> {
|
async createBucketFolder(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
@@ -320,7 +320,7 @@ class WebdavplistApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadBucketFile (configMap: IStringKeyMap): Promise<boolean> {
|
async downloadBucketFile(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
const { downloadPath, fileArray, maxDownloadFileCount } = configMap
|
||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
const promises = [] as any
|
const promises = [] as any
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ interface IJSON {
|
|||||||
class ManageDB {
|
class ManageDB {
|
||||||
readonly #ctx: IManageApiType
|
readonly #ctx: IManageApiType
|
||||||
readonly #db: JSONStore
|
readonly #db: JSONStore
|
||||||
constructor (ctx: IManageApiType) {
|
constructor(ctx: IManageApiType) {
|
||||||
this.#ctx = ctx
|
this.#ctx = ctx
|
||||||
this.#db = new JSONStore(this.#ctx.configPath)
|
this.#db = new JSONStore(this.#ctx.configPath)
|
||||||
const initParams: IStringKeyMap = {
|
const initParams: IStringKeyMap = {
|
||||||
@@ -28,37 +28,37 @@ class ManageDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
read (flush?: boolean): IJSON {
|
read(flush?: boolean): IJSON {
|
||||||
return this.#db.read(flush)
|
return this.#db.read(flush)
|
||||||
}
|
}
|
||||||
|
|
||||||
get (key: string = ''): any {
|
get(key: string = ''): any {
|
||||||
this.read(true)
|
this.read(true)
|
||||||
return this.#db.get(key)
|
return this.#db.get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
set (key: string, value: any): void {
|
set(key: string, value: any): void {
|
||||||
this.read(true)
|
this.read(true)
|
||||||
return this.#db.set(key, value)
|
return this.#db.set(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
has (key: string): boolean {
|
has(key: string): boolean {
|
||||||
this.read(true)
|
this.read(true)
|
||||||
return this.#db.has(key)
|
return this.#db.has(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
unset (key: string, value: any): boolean {
|
unset(key: string, value: any): boolean {
|
||||||
this.read(true)
|
this.read(true)
|
||||||
return this.#db.unset(key, value)
|
return this.#db.unset(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
saveConfig (config: Partial<IManageConfigType>): void {
|
saveConfig(config: Partial<IManageConfigType>): void {
|
||||||
Object.keys(config).forEach((name: string) => {
|
Object.keys(config).forEach((name: string) => {
|
||||||
this.set(name, config[name])
|
this.set(name, config[name])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
removeConfig (config: IManageConfigType): void {
|
removeConfig(config: IManageConfigType): void {
|
||||||
Object.keys(config).forEach((name: string) => {
|
Object.keys(config).forEach((name: string) => {
|
||||||
this.unset(name, config[name])
|
this.unset(name, config[name])
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const errorMsg = {
|
|||||||
brokenButBackup: $t('TIPS_PICGO_CONFIG_FILE_BROKEN_WITH_BACKUP')
|
brokenButBackup: $t('TIPS_PICGO_CONFIG_FILE_BROKEN_WITH_BACKUP')
|
||||||
}
|
}
|
||||||
|
|
||||||
function manageDbChecker () {
|
function manageDbChecker() {
|
||||||
if (process.type !== 'renderer') {
|
if (process.type !== 'renderer') {
|
||||||
const manageConfigFilePath = managePathChecker()
|
const manageConfigFilePath = managePathChecker()
|
||||||
if (!fs.existsSync(manageConfigFilePath)) {
|
if (!fs.existsSync(manageConfigFilePath)) {
|
||||||
@@ -72,7 +72,7 @@ function manageDbChecker () {
|
|||||||
/**
|
/**
|
||||||
* Get manage config path
|
* Get manage config path
|
||||||
*/
|
*/
|
||||||
function managePathChecker (): string {
|
function managePathChecker(): string {
|
||||||
if (_configFilePath) {
|
if (_configFilePath) {
|
||||||
return _configFilePath
|
return _configFilePath
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,7 @@ function managePathChecker (): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function managePathDir () {
|
function managePathDir() {
|
||||||
return path.dirname(managePathChecker())
|
return path.dirname(managePathChecker())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,38 +18,38 @@ class UpDownTaskQueue {
|
|||||||
|
|
||||||
private persistPath = path.join(app.getPath('userData'), 'UpDownTaskQueue.json')
|
private persistPath = path.join(app.getPath('userData'), 'UpDownTaskQueue.json')
|
||||||
|
|
||||||
private constructor () {
|
private constructor() {
|
||||||
this.restore()
|
this.restore()
|
||||||
}
|
}
|
||||||
|
|
||||||
static getInstance () {
|
static getInstance() {
|
||||||
if (!UpDownTaskQueue.instance) {
|
if (!UpDownTaskQueue.instance) {
|
||||||
UpDownTaskQueue.instance = new UpDownTaskQueue()
|
UpDownTaskQueue.instance = new UpDownTaskQueue()
|
||||||
}
|
}
|
||||||
return UpDownTaskQueue.instance
|
return UpDownTaskQueue.instance
|
||||||
}
|
}
|
||||||
|
|
||||||
getUploadTaskQueue () {
|
getUploadTaskQueue() {
|
||||||
return UpDownTaskQueue.getInstance().uploadTaskQueue
|
return UpDownTaskQueue.getInstance().uploadTaskQueue
|
||||||
}
|
}
|
||||||
|
|
||||||
getDownloadTaskQueue () {
|
getDownloadTaskQueue() {
|
||||||
return UpDownTaskQueue.getInstance().downloadTaskQueue
|
return UpDownTaskQueue.getInstance().downloadTaskQueue
|
||||||
}
|
}
|
||||||
|
|
||||||
getUploadTask (taskId: string) {
|
getUploadTask(taskId: string) {
|
||||||
return UpDownTaskQueue.getInstance().uploadTaskQueue.find(item => item.id === taskId)
|
return UpDownTaskQueue.getInstance().uploadTaskQueue.find(item => item.id === taskId)
|
||||||
}
|
}
|
||||||
|
|
||||||
getAllUploadTask () {
|
getAllUploadTask() {
|
||||||
return UpDownTaskQueue.getInstance().uploadTaskQueue
|
return UpDownTaskQueue.getInstance().uploadTaskQueue
|
||||||
}
|
}
|
||||||
|
|
||||||
addUploadTask (task: IUploadTask) {
|
addUploadTask(task: IUploadTask) {
|
||||||
UpDownTaskQueue.getInstance().uploadTaskQueue.push(task)
|
UpDownTaskQueue.getInstance().uploadTaskQueue.push(task)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateUploadTask (task: Partial<IUploadTask>) {
|
updateUploadTask(task: Partial<IUploadTask>) {
|
||||||
const taskIndex = UpDownTaskQueue.getInstance().uploadTaskQueue.findIndex(item => item.id === task.id)
|
const taskIndex = UpDownTaskQueue.getInstance().uploadTaskQueue.findIndex(item => item.id === task.id)
|
||||||
if (taskIndex !== -1) {
|
if (taskIndex !== -1) {
|
||||||
const taskKeys = Object.keys(task)
|
const taskKeys = Object.keys(task)
|
||||||
@@ -61,33 +61,33 @@ class UpDownTaskQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeUploadTask (taskId: string) {
|
removeUploadTask(taskId: string) {
|
||||||
const taskIndex = UpDownTaskQueue.getInstance().uploadTaskQueue.findIndex(item => item.id === taskId)
|
const taskIndex = UpDownTaskQueue.getInstance().uploadTaskQueue.findIndex(item => item.id === taskId)
|
||||||
if (taskIndex !== -1) {
|
if (taskIndex !== -1) {
|
||||||
UpDownTaskQueue.getInstance().uploadTaskQueue.splice(taskIndex, 1)
|
UpDownTaskQueue.getInstance().uploadTaskQueue.splice(taskIndex, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeDownloadTask (taskId: string) {
|
removeDownloadTask(taskId: string) {
|
||||||
const taskIndex = UpDownTaskQueue.getInstance().downloadTaskQueue.findIndex(item => item.id === taskId)
|
const taskIndex = UpDownTaskQueue.getInstance().downloadTaskQueue.findIndex(item => item.id === taskId)
|
||||||
if (taskIndex !== -1) {
|
if (taskIndex !== -1) {
|
||||||
UpDownTaskQueue.getInstance().downloadTaskQueue.splice(taskIndex, 1)
|
UpDownTaskQueue.getInstance().downloadTaskQueue.splice(taskIndex, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getDownloadTask (taskId: string) {
|
getDownloadTask(taskId: string) {
|
||||||
return UpDownTaskQueue.getInstance().downloadTaskQueue.find(item => item.id === taskId)
|
return UpDownTaskQueue.getInstance().downloadTaskQueue.find(item => item.id === taskId)
|
||||||
}
|
}
|
||||||
|
|
||||||
getAllDownloadTask () {
|
getAllDownloadTask() {
|
||||||
return UpDownTaskQueue.getInstance().downloadTaskQueue
|
return UpDownTaskQueue.getInstance().downloadTaskQueue
|
||||||
}
|
}
|
||||||
|
|
||||||
addDownloadTask (task: IDownloadTask) {
|
addDownloadTask(task: IDownloadTask) {
|
||||||
UpDownTaskQueue.getInstance().downloadTaskQueue.push(task)
|
UpDownTaskQueue.getInstance().downloadTaskQueue.push(task)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDownloadTask (task: Partial<IDownloadTask>) {
|
updateDownloadTask(task: Partial<IDownloadTask>) {
|
||||||
const taskIndex = UpDownTaskQueue.getInstance().downloadTaskQueue.findIndex(item => item.id === task.id)
|
const taskIndex = UpDownTaskQueue.getInstance().downloadTaskQueue.findIndex(item => item.id === task.id)
|
||||||
if (taskIndex !== -1) {
|
if (taskIndex !== -1) {
|
||||||
const taskKeys = Object.keys(task)
|
const taskKeys = Object.keys(task)
|
||||||
@@ -99,11 +99,11 @@ class UpDownTaskQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clearUploadTaskQueue () {
|
clearUploadTaskQueue() {
|
||||||
UpDownTaskQueue.getInstance().uploadTaskQueue = []
|
UpDownTaskQueue.getInstance().uploadTaskQueue = []
|
||||||
}
|
}
|
||||||
|
|
||||||
removeUploadedTask () {
|
removeUploadedTask() {
|
||||||
UpDownTaskQueue.getInstance().uploadTaskQueue = UpDownTaskQueue.getInstance().uploadTaskQueue.filter(
|
UpDownTaskQueue.getInstance().uploadTaskQueue = UpDownTaskQueue.getInstance().uploadTaskQueue.filter(
|
||||||
item =>
|
item =>
|
||||||
item.status !== uploadTaskSpecialStatus.uploaded &&
|
item.status !== uploadTaskSpecialStatus.uploaded &&
|
||||||
@@ -112,7 +112,7 @@ class UpDownTaskQueue {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
removeDownloadedTask () {
|
removeDownloadedTask() {
|
||||||
UpDownTaskQueue.getInstance().downloadTaskQueue = UpDownTaskQueue.getInstance().downloadTaskQueue.filter(
|
UpDownTaskQueue.getInstance().downloadTaskQueue = UpDownTaskQueue.getInstance().downloadTaskQueue.filter(
|
||||||
item =>
|
item =>
|
||||||
item.status !== downloadTaskSpecialStatus.downloaded &&
|
item.status !== downloadTaskSpecialStatus.downloaded &&
|
||||||
@@ -121,16 +121,16 @@ class UpDownTaskQueue {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
clearDownloadTaskQueue () {
|
clearDownloadTaskQueue() {
|
||||||
UpDownTaskQueue.getInstance().downloadTaskQueue = []
|
UpDownTaskQueue.getInstance().downloadTaskQueue = []
|
||||||
}
|
}
|
||||||
|
|
||||||
clearAllTaskQueue () {
|
clearAllTaskQueue() {
|
||||||
this.clearUploadTaskQueue()
|
this.clearUploadTaskQueue()
|
||||||
this.clearDownloadTaskQueue()
|
this.clearDownloadTaskQueue()
|
||||||
}
|
}
|
||||||
|
|
||||||
persist () {
|
persist() {
|
||||||
try {
|
try {
|
||||||
this.checkPersistPath()
|
this.checkPersistPath()
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
@@ -145,7 +145,7 @@ class UpDownTaskQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private restore () {
|
private restore() {
|
||||||
try {
|
try {
|
||||||
this.checkPersistPath()
|
this.checkPersistPath()
|
||||||
const persistData = JSON.parse(fs.readFileSync(this.persistPath, { encoding: 'utf-8' }))
|
const persistData = JSON.parse(fs.readFileSync(this.persistPath, { encoding: 'utf-8' }))
|
||||||
@@ -157,7 +157,7 @@ class UpDownTaskQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkPersistPath () {
|
private checkPersistPath() {
|
||||||
if (!fs.existsSync(this.persistPath)) {
|
if (!fs.existsSync(this.persistPath)) {
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
this.persistPath,
|
this.persistPath,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
logger: ManageLogger
|
logger: ManageLogger
|
||||||
currentPicBedConfig: IPicBedMangeConfig
|
currentPicBedConfig: IPicBedMangeConfig
|
||||||
|
|
||||||
constructor (currentPicBed: string = '') {
|
constructor(currentPicBed: string = '') {
|
||||||
super()
|
super()
|
||||||
this.currentPicBed = currentPicBed || 'placeholder'
|
this.currentPicBed = currentPicBed || 'placeholder'
|
||||||
this.configPath = managePathChecker()
|
this.configPath = managePathChecker()
|
||||||
@@ -36,7 +36,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
this.currentPicBedConfig = this.getPicBedConfig(this.currentPicBed)
|
this.currentPicBedConfig = this.getPicBedConfig(this.currentPicBed)
|
||||||
}
|
}
|
||||||
|
|
||||||
getMsgParam (method: string) {
|
getMsgParam(method: string) {
|
||||||
return {
|
return {
|
||||||
class: 'ManageApi',
|
class: 'ManageApi',
|
||||||
method,
|
method,
|
||||||
@@ -44,11 +44,11 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
errorMsg (err: any, param: IStringKeyMap) {
|
errorMsg(err: any, param: IStringKeyMap) {
|
||||||
this.logger.error(formatError(err, param))
|
this.logger.error(formatError(err, param))
|
||||||
}
|
}
|
||||||
|
|
||||||
createClient () {
|
createClient() {
|
||||||
const name = this.currentPicBedConfig.picBedName
|
const name = this.currentPicBedConfig.picBedName
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'aliyun':
|
case 'aliyun':
|
||||||
@@ -127,11 +127,11 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getPicBedConfig (picBedName: string): IPicBedMangeConfig {
|
private getPicBedConfig(picBedName: string): IPicBedMangeConfig {
|
||||||
return this.getConfig<IPicBedMangeConfig>(`picBed.${picBedName}`)
|
return this.getConfig<IPicBedMangeConfig>(`picBed.${picBedName}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
private initConfigPath (): void {
|
private initConfigPath(): void {
|
||||||
if (this.configPath === '') {
|
if (this.configPath === '') {
|
||||||
this.configPath = `${homedir()}/.piclist/manage.json`
|
this.configPath = `${homedir()}/.piclist/manage.json`
|
||||||
}
|
}
|
||||||
@@ -146,7 +146,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private initconfig (): void {
|
private initconfig(): void {
|
||||||
this.db = new ManageDB(this)
|
this.db = new ManageDB(this)
|
||||||
this._config = this.db.read(true) as IManageConfigType
|
this._config = this.db.read(true) as IManageConfigType
|
||||||
}
|
}
|
||||||
@@ -158,7 +158,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
return get(this._config, name)
|
return get(this._config, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
saveConfig (config: IStringKeyMap): void {
|
saveConfig(config: IStringKeyMap): void {
|
||||||
if (!isInputConfigValid(config)) {
|
if (!isInputConfigValid(config)) {
|
||||||
this.logger.warn('the format of config is invalid, please provide object')
|
this.logger.warn('the format of config is invalid, please provide object')
|
||||||
return
|
return
|
||||||
@@ -167,7 +167,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
this.db.saveConfig(config)
|
this.db.saveConfig(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
removeConfig (key: string, propName: string): void {
|
removeConfig(key: string, propName: string): void {
|
||||||
if (!key || !propName) {
|
if (!key || !propName) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -175,7 +175,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
this.db.unset(key, propName)
|
this.db.unset(key, propName)
|
||||||
}
|
}
|
||||||
|
|
||||||
setConfig (config: IStringKeyMap): void {
|
setConfig(config: IStringKeyMap): void {
|
||||||
if (!isInputConfigValid(config)) {
|
if (!isInputConfigValid(config)) {
|
||||||
this.logger.warn('the format of config is invalid, please provide object')
|
this.logger.warn('the format of config is invalid, please provide object')
|
||||||
return
|
return
|
||||||
@@ -185,12 +185,12 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unsetConfig (key: string, propName: string): void {
|
unsetConfig(key: string, propName: string): void {
|
||||||
if (!key || !propName) return
|
if (!key || !propName) return
|
||||||
unset(this.getConfig(key), propName)
|
unset(this.getConfig(key), propName)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketList (param?: IStringKeyMap | undefined): Promise<any> {
|
async getBucketList(param?: IStringKeyMap | undefined): Promise<any> {
|
||||||
let client
|
let client
|
||||||
const name = this.currentPicBedConfig.picBedName.replace('plist', '')
|
const name = this.currentPicBedConfig.picBedName.replace('plist', '')
|
||||||
switch (this.currentPicBedConfig.picBedName) {
|
switch (this.currentPicBedConfig.picBedName) {
|
||||||
@@ -232,12 +232,12 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketInfo (param?: IStringKeyMap | undefined): Promise<IStringKeyMap | IManageError> {
|
async getBucketInfo(param?: IStringKeyMap | undefined): Promise<IStringKeyMap | IManageError> {
|
||||||
console.log(param)
|
console.log(param)
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketDomain (param: IStringKeyMap): Promise<IStringKeyMap | IManageError> {
|
async getBucketDomain(param: IStringKeyMap): Promise<IStringKeyMap | IManageError> {
|
||||||
let client
|
let client
|
||||||
switch (this.currentPicBedConfig.picBedName) {
|
switch (this.currentPicBedConfig.picBedName) {
|
||||||
case 'tcyun':
|
case 'tcyun':
|
||||||
@@ -262,7 +262,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async createBucket (param?: IStringKeyMap): Promise<boolean> {
|
async createBucket(param?: IStringKeyMap): Promise<boolean> {
|
||||||
let client
|
let client
|
||||||
switch (this.currentPicBedConfig.picBedName) {
|
switch (this.currentPicBedConfig.picBedName) {
|
||||||
case 'tcyun':
|
case 'tcyun':
|
||||||
@@ -281,32 +281,32 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteBucket (param?: IStringKeyMap): Promise<boolean> {
|
async deleteBucket(param?: IStringKeyMap): Promise<boolean> {
|
||||||
console.log(param)
|
console.log(param)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOperatorList (param?: IStringKeyMap): Promise<string[] | IManageError> {
|
async getOperatorList(param?: IStringKeyMap): Promise<string[] | IManageError> {
|
||||||
console.log(param)
|
console.log(param)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
async addOperator (param?: IStringKeyMap): Promise<boolean> {
|
async addOperator(param?: IStringKeyMap): Promise<boolean> {
|
||||||
console.log(param)
|
console.log(param)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteOperator (param?: IStringKeyMap): Promise<boolean> {
|
async deleteOperator(param?: IStringKeyMap): Promise<boolean> {
|
||||||
console.log(param)
|
console.log(param)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketAclPolicy (param?: IStringKeyMap): Promise<IStringKeyMap | IManageError> {
|
async getBucketAclPolicy(param?: IStringKeyMap): Promise<IStringKeyMap | IManageError> {
|
||||||
console.log(param)
|
console.log(param)
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
async setBucketAclPolicy (param?: IStringKeyMap): Promise<boolean> {
|
async setBucketAclPolicy(param?: IStringKeyMap): Promise<boolean> {
|
||||||
let client
|
let client
|
||||||
switch (this.currentPicBedConfig.picBedName) {
|
switch (this.currentPicBedConfig.picBedName) {
|
||||||
case 'qiniu':
|
case 'qiniu':
|
||||||
@@ -322,7 +322,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucketListRecursively (param?: IStringKeyMap): Promise<IStringKeyMap | IManageError> {
|
async getBucketListRecursively(param?: IStringKeyMap): Promise<IStringKeyMap | IManageError> {
|
||||||
let client
|
let client
|
||||||
let window
|
let window
|
||||||
const defaultResult = {
|
const defaultResult = {
|
||||||
@@ -365,7 +365,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
* @param param
|
* @param param
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async getBucketListBackstage (param?: IStringKeyMap): Promise<IStringKeyMap | IManageError> {
|
async getBucketListBackstage(param?: IStringKeyMap): Promise<IStringKeyMap | IManageError> {
|
||||||
let client
|
let client
|
||||||
let window
|
let window
|
||||||
const defaultResult = {
|
const defaultResult = {
|
||||||
@@ -412,7 +412,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
* isDir: 是否是文件夹
|
* isDir: 是否是文件夹
|
||||||
* fileSize: 文件大小
|
* fileSize: 文件大小
|
||||||
**/
|
**/
|
||||||
async getBucketFileList (param?: IStringKeyMap): Promise<IStringKeyMap | IManageError> {
|
async getBucketFileList(param?: IStringKeyMap): Promise<IStringKeyMap | IManageError> {
|
||||||
const defaultResponse = {
|
const defaultResponse = {
|
||||||
fullList: [] as any,
|
fullList: [] as any,
|
||||||
isTruncated: false,
|
isTruncated: false,
|
||||||
@@ -439,7 +439,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteBucketFile (param?: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFile(param?: IStringKeyMap): Promise<boolean> {
|
||||||
let client
|
let client
|
||||||
switch (this.currentPicBedConfig.picBedName) {
|
switch (this.currentPicBedConfig.picBedName) {
|
||||||
case 'tcyun':
|
case 'tcyun':
|
||||||
@@ -466,7 +466,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteBucketFolder (param?: IStringKeyMap): Promise<boolean> {
|
async deleteBucketFolder(param?: IStringKeyMap): Promise<boolean> {
|
||||||
let client
|
let client
|
||||||
switch (this.currentPicBedConfig.picBedName) {
|
switch (this.currentPicBedConfig.picBedName) {
|
||||||
case 'tcyun':
|
case 'tcyun':
|
||||||
@@ -490,7 +490,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async renameBucketFile (param?: IStringKeyMap): Promise<boolean> {
|
async renameBucketFile(param?: IStringKeyMap): Promise<boolean> {
|
||||||
let client
|
let client
|
||||||
switch (this.currentPicBedConfig.picBedName) {
|
switch (this.currentPicBedConfig.picBedName) {
|
||||||
case 'tcyun':
|
case 'tcyun':
|
||||||
@@ -513,7 +513,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadBucketFile (param?: IStringKeyMap): Promise<boolean> {
|
async downloadBucketFile(param?: IStringKeyMap): Promise<boolean> {
|
||||||
let client
|
let client
|
||||||
switch (this.currentPicBedConfig.picBedName) {
|
switch (this.currentPicBedConfig.picBedName) {
|
||||||
case 'tcyun':
|
case 'tcyun':
|
||||||
@@ -540,12 +540,12 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async copyMoveBucketFile (param?: IStringKeyMap): Promise<boolean> {
|
async copyMoveBucketFile(param?: IStringKeyMap): Promise<boolean> {
|
||||||
console.log(param)
|
console.log(param)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
async createBucketFolder (param?: IStringKeyMap): Promise<boolean> {
|
async createBucketFolder(param?: IStringKeyMap): Promise<boolean> {
|
||||||
let client
|
let client
|
||||||
switch (this.currentPicBedConfig.picBedName) {
|
switch (this.currentPicBedConfig.picBedName) {
|
||||||
case 'tcyun':
|
case 'tcyun':
|
||||||
@@ -569,7 +569,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async uploadBucketFile (param?: IStringKeyMap): Promise<boolean> {
|
async uploadBucketFile(param?: IStringKeyMap): Promise<boolean> {
|
||||||
let client
|
let client
|
||||||
switch (this.currentPicBedConfig.picBedName) {
|
switch (this.currentPicBedConfig.picBedName) {
|
||||||
case 'tcyun':
|
case 'tcyun':
|
||||||
@@ -595,7 +595,7 @@ export class ManageApi extends EventEmitter implements IManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPreSignedUrl (param?: IStringKeyMap): Promise<string> {
|
async getPreSignedUrl(param?: IStringKeyMap): Promise<string> {
|
||||||
let client
|
let client
|
||||||
switch (this.currentPicBedConfig.picBedName) {
|
switch (this.currentPicBedConfig.picBedName) {
|
||||||
case 'tcyun':
|
case 'tcyun':
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export const getFSFile = async (filePath: string, stream: boolean = false): Prom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isInputConfigValid (config: any): boolean {
|
export function isInputConfigValid(config: any): boolean {
|
||||||
return typeof config === 'object' && !Array.isArray(config) && Object.keys(config).length > 0
|
return typeof config === 'object' && !Array.isArray(config) && Object.keys(config).length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,7 +280,7 @@ export const getInnerAgent = (proxy: any, sslEnabled: boolean = true) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getOptions (
|
export function getOptions(
|
||||||
method?: string,
|
method?: string,
|
||||||
headers?: IStringKeyMap,
|
headers?: IStringKeyMap,
|
||||||
searchParams?: IStringKeyMap,
|
searchParams?: IStringKeyMap,
|
||||||
@@ -309,14 +309,14 @@ export class ConcurrencyPromisePool {
|
|||||||
runningNum: number
|
runningNum: number
|
||||||
results: any[]
|
results: any[]
|
||||||
|
|
||||||
constructor (limit: number) {
|
constructor(limit: number) {
|
||||||
this.limit = limit
|
this.limit = limit
|
||||||
this.queue = []
|
this.queue = []
|
||||||
this.runningNum = 0
|
this.runningNum = 0
|
||||||
this.results = []
|
this.results = []
|
||||||
}
|
}
|
||||||
|
|
||||||
all (promises: any[] = []) {
|
all(promises: any[] = []) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
for (const promise of promises) {
|
for (const promise of promises) {
|
||||||
this._run(promise, resolve, reject)
|
this._run(promise, resolve, reject)
|
||||||
@@ -324,7 +324,7 @@ export class ConcurrencyPromisePool {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_run (promise: any, resolve: any, reject: any) {
|
_run(promise: any, resolve: any, reject: any) {
|
||||||
if (this.runningNum >= this.limit) {
|
if (this.runningNum >= this.limit) {
|
||||||
this.queue.push(promise)
|
this.queue.push(promise)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export interface DogecloudToken {
|
|||||||
sessionToken: string
|
sessionToken: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function dogecloudApi (
|
export async function dogecloudApi(
|
||||||
apiPath: string,
|
apiPath: string,
|
||||||
data = {},
|
data = {},
|
||||||
jsonMode: boolean = false,
|
jsonMode: boolean = false,
|
||||||
@@ -45,7 +45,7 @@ export async function dogecloudApi (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getTempToken (accessKey: string, secretKey: string): Promise<IObj | DogecloudToken> {
|
export async function getTempToken(accessKey: string, secretKey: string): Promise<IObj | DogecloudToken> {
|
||||||
const dogeTempToken = (await picgo.getConfig('Credentials.doge-token')) || ({} as any)
|
const dogeTempToken = (await picgo.getConfig('Credentials.doge-token')) || ({} as any)
|
||||||
if (dogeTempToken.token && dogeTempToken.expires > Date.now() + 7200000) {
|
if (dogeTempToken.token && dogeTempToken.expires > Date.now() + 7200000) {
|
||||||
return dogeTempToken.token
|
return dogeTempToken.token
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ export class ManageLogger implements ILogger {
|
|||||||
#logLevel!: string
|
#logLevel!: string
|
||||||
#logPath!: string
|
#logPath!: string
|
||||||
|
|
||||||
constructor (ctx: IManageApiType) {
|
constructor(ctx: IManageApiType) {
|
||||||
this.#ctx = ctx
|
this.#ctx = ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
#handleLog (type: string, ...msg: ILogArgvTypeWithError[]): void {
|
#handleLog(type: string, ...msg: ILogArgvTypeWithError[]): void {
|
||||||
const logHeader = chalk[this.#level[type] as ILogColor](`[PicList ${type.toUpperCase()}]`)
|
const logHeader = chalk[this.#level[type] as ILogColor](`[PicList ${type.toUpperCase()}]`)
|
||||||
console.log(logHeader, ...msg)
|
console.log(logHeader, ...msg)
|
||||||
this.#logLevel = this.#ctx.getConfig(configPaths.settings.logLevel)
|
this.#logLevel = this.#ctx.getConfig(configPaths.settings.logLevel)
|
||||||
@@ -53,7 +53,7 @@ export class ManageLogger implements ILogger {
|
|||||||
}, 0)
|
}, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
#checkLogFileIsLarge (logPath: string): {
|
#checkLogFileIsLarge(logPath: string): {
|
||||||
isLarge: boolean
|
isLarge: boolean
|
||||||
logFileSize?: number
|
logFileSize?: number
|
||||||
logFileSizeLimit?: number
|
logFileSizeLimit?: number
|
||||||
@@ -76,14 +76,14 @@ export class ManageLogger implements ILogger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#recreateLogFile (logPath: string): void {
|
#recreateLogFile(logPath: string): void {
|
||||||
if (fs.existsSync(logPath)) {
|
if (fs.existsSync(logPath)) {
|
||||||
fs.unlinkSync(logPath)
|
fs.unlinkSync(logPath)
|
||||||
fs.createFileSync(logPath)
|
fs.createFileSync(logPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#handleWriteLog (logPath: string, type: string, ...msg: ILogArgvTypeWithError[]): void {
|
#handleWriteLog(logPath: string, type: string, ...msg: ILogArgvTypeWithError[]): void {
|
||||||
try {
|
try {
|
||||||
if (this.#checkLogLevel(type, this.#logLevel)) {
|
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()}] `
|
||||||
@@ -98,7 +98,7 @@ export class ManageLogger implements ILogger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#formatLogItem (item: ILogArgvTypeWithError, type: string): string {
|
#formatLogItem(item: ILogArgvTypeWithError, type: string): string {
|
||||||
let result = ''
|
let result = ''
|
||||||
if (item instanceof Error && type === 'error') {
|
if (item instanceof Error && type === 'error') {
|
||||||
result += `\n------Error Stack Begin------\n${util.format(item?.stack)}\n-------Error Stack End------- `
|
result += `\n------Error Stack Begin------\n${util.format(item?.stack)}\n-------Error Stack End------- `
|
||||||
@@ -114,7 +114,7 @@ export class ManageLogger implements ILogger {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
#checkLogLevel (type: string, level: undefined | string | string[]): boolean {
|
#checkLogLevel(type: string, level: undefined | string | string[]): boolean {
|
||||||
if (level === undefined || level === 'all') {
|
if (level === undefined || level === 'all') {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -124,23 +124,23 @@ export class ManageLogger implements ILogger {
|
|||||||
return type === level
|
return type === level
|
||||||
}
|
}
|
||||||
|
|
||||||
success (...msq: ILogArgvType[]): void {
|
success(...msq: ILogArgvType[]): void {
|
||||||
return this.#handleLog(ILogType.success, ...msq)
|
return this.#handleLog(ILogType.success, ...msq)
|
||||||
}
|
}
|
||||||
|
|
||||||
info (...msq: ILogArgvType[]): void {
|
info(...msq: ILogArgvType[]): void {
|
||||||
return this.#handleLog(ILogType.info, ...msq)
|
return this.#handleLog(ILogType.info, ...msq)
|
||||||
}
|
}
|
||||||
|
|
||||||
error (...msq: ILogArgvTypeWithError[]): void {
|
error(...msq: ILogArgvTypeWithError[]): void {
|
||||||
return this.#handleLog(ILogType.error, ...msq)
|
return this.#handleLog(ILogType.error, ...msq)
|
||||||
}
|
}
|
||||||
|
|
||||||
warn (...msq: ILogArgvType[]): void {
|
warn(...msq: ILogArgvType[]): void {
|
||||||
return this.#handleLog(ILogType.warn, ...msq)
|
return this.#handleLog(ILogType.warn, ...msq)
|
||||||
}
|
}
|
||||||
|
|
||||||
debug (...msq: ILogArgvType[]): void {
|
debug(...msq: ILogArgvType[]): void {
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
this.#handleLog(ILogType.info, ...msq)
|
this.#handleLog(ILogType.info, ...msq)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,12 +41,12 @@ class Server {
|
|||||||
#httpServer: http.Server
|
#httpServer: http.Server
|
||||||
#config: IServerConfig
|
#config: IServerConfig
|
||||||
|
|
||||||
constructor () {
|
constructor() {
|
||||||
this.#config = this.getConfigWithDefaults()
|
this.#config = this.getConfigWithDefaults()
|
||||||
this.#httpServer = http.createServer(this.#handleRequest)
|
this.#httpServer = http.createServer(this.#handleRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
getConfigWithDefaults () {
|
getConfigWithDefaults() {
|
||||||
let config = picgo.getConfig<IServerConfig>(configPaths.settings.server)
|
let config = picgo.getConfig<IServerConfig>(configPaths.settings.server)
|
||||||
if (!this.#isValidConfig(config)) {
|
if (!this.#isValidConfig(config)) {
|
||||||
config = { port: DEFAULT_PORT, host: DEFAULT_HOST, enable: true }
|
config = { port: DEFAULT_PORT, host: DEFAULT_HOST, enable: true }
|
||||||
@@ -55,7 +55,7 @@ class Server {
|
|||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
#isValidConfig (config: IObj | undefined) {
|
#isValidConfig(config: IObj | undefined) {
|
||||||
return config && config.port && config.host && config.enable !== undefined
|
return config && config.port && config.host && config.enable !== undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,20 +198,20 @@ class Server {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
startup () {
|
startup() {
|
||||||
if (this.#config.enable) {
|
if (this.#config.enable) {
|
||||||
this.#listen(this.#config.port)
|
this.#listen(this.#config.port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shutdown (hasStarted?: boolean) {
|
shutdown(hasStarted?: boolean) {
|
||||||
this.#httpServer.close()
|
this.#httpServer.close()
|
||||||
if (!hasStarted) {
|
if (!hasStarted) {
|
||||||
logger.info('[PicList Server] shutdown')
|
logger.info('[PicList Server] shutdown')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
restart () {
|
restart() {
|
||||||
this.shutdown()
|
this.shutdown()
|
||||||
this.#config = this.getConfigWithDefaults()
|
this.#config = this.getConfigWithDefaults()
|
||||||
this.startup()
|
this.startup()
|
||||||
|
|||||||
@@ -5,27 +5,27 @@ type HttpMethod = 'GET' | 'POST'
|
|||||||
class Router {
|
class Router {
|
||||||
#router = new Map<string, Map<HttpMethod, { handler: routeHandler; urlparams?: URLSearchParams }>>()
|
#router = new Map<string, Map<HttpMethod, { handler: routeHandler; urlparams?: URLSearchParams }>>()
|
||||||
|
|
||||||
#addRoute (method: HttpMethod, url: string, callback: routeHandler, urlparams?: URLSearchParams): void {
|
#addRoute(method: HttpMethod, url: string, callback: routeHandler, urlparams?: URLSearchParams): void {
|
||||||
if (!this.#router.has(url)) {
|
if (!this.#router.has(url)) {
|
||||||
this.#router.set(url, new Map())
|
this.#router.set(url, new Map())
|
||||||
}
|
}
|
||||||
this.#router.get(url)!.set(method, { handler: callback, urlparams })
|
this.#router.get(url)!.set(method, { handler: callback, urlparams })
|
||||||
}
|
}
|
||||||
|
|
||||||
get (url: string, callback: routeHandler, urlparams?: URLSearchParams): void {
|
get(url: string, callback: routeHandler, urlparams?: URLSearchParams): void {
|
||||||
this.#addRoute('GET', url, callback, urlparams)
|
this.#addRoute('GET', url, callback, urlparams)
|
||||||
}
|
}
|
||||||
|
|
||||||
post (url: string, callback: routeHandler, urlparams?: URLSearchParams): void {
|
post(url: string, callback: routeHandler, urlparams?: URLSearchParams): void {
|
||||||
this.#addRoute('POST', url, callback, urlparams)
|
this.#addRoute('POST', url, callback, urlparams)
|
||||||
}
|
}
|
||||||
|
|
||||||
any (url: string, callback: routeHandler, urlparams?: URLSearchParams): void {
|
any(url: string, callback: routeHandler, urlparams?: URLSearchParams): void {
|
||||||
this.#addRoute('GET', url, callback, urlparams)
|
this.#addRoute('GET', url, callback, urlparams)
|
||||||
this.#addRoute('POST', url, callback, urlparams)
|
this.#addRoute('POST', url, callback, urlparams)
|
||||||
}
|
}
|
||||||
|
|
||||||
getHandler (url: string, method: HttpMethod) {
|
getHandler(url: string, method: HttpMethod) {
|
||||||
if (this.#router.has(url)) {
|
if (this.#router.has(url)) {
|
||||||
const methods = this.#router.get(url)!
|
const methods = this.#router.get(url)!
|
||||||
if (methods.has(method)) {
|
if (methods.has(method)) {
|
||||||
|
|||||||
@@ -1,234 +1,234 @@
|
|||||||
import http from 'node:http'
|
import http from 'node:http'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
|
|
||||||
import { dbPathDir } from '@core/datastore/dbChecker'
|
import { dbPathDir } from '@core/datastore/dbChecker'
|
||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
import logger from '@core/picgo/logger'
|
import logger from '@core/picgo/logger'
|
||||||
import { uploadChoosedFiles, uploadClipboardFiles } from 'apis/app/uploader/apis'
|
import { uploadChoosedFiles, uploadClipboardFiles } from 'apis/app/uploader/apis'
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
import { app } from 'electron'
|
import { app } from 'electron'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import { marked } from 'marked'
|
import { marked } from 'marked'
|
||||||
|
|
||||||
import type { IHttpResponse, IStringKeyMap } from '#/types/types'
|
import type { IHttpResponse, IStringKeyMap } from '#/types/types'
|
||||||
import { markdownContent } from '~/server/apiDoc'
|
import { markdownContent } from '~/server/apiDoc'
|
||||||
import router from '~/server/router'
|
import router from '~/server/router'
|
||||||
import { deleteChoosedFiles, handleResponse } from '~/server/utils'
|
import { deleteChoosedFiles, handleResponse } from '~/server/utils'
|
||||||
import { AESHelper } from '~/utils/aesHelper'
|
import { AESHelper } from '~/utils/aesHelper'
|
||||||
import { configPaths } from '~/utils/configPaths'
|
import { configPaths } from '~/utils/configPaths'
|
||||||
import { changeCurrentUploader } from '~/utils/handleUploaderConfig'
|
import { changeCurrentUploader } from '~/utils/handleUploaderConfig'
|
||||||
|
|
||||||
const appPath = app.getPath('userData')
|
const appPath = app.getPath('userData')
|
||||||
const serverTempDir = path.join(appPath, 'serverTemp')
|
const serverTempDir = path.join(appPath, 'serverTemp')
|
||||||
|
|
||||||
const STORE_PATH = dbPathDir()
|
const STORE_PATH = dbPathDir()
|
||||||
const LOG_PATH = path.join(STORE_PATH, 'piclist.log')
|
const LOG_PATH = path.join(STORE_PATH, 'piclist.log')
|
||||||
|
|
||||||
const errorMessage = `upload error. see ${LOG_PATH} for more detail.`
|
const errorMessage = `upload error. see ${LOG_PATH} for more detail.`
|
||||||
const deleteErrorMessage = `delete error. see ${LOG_PATH} for more detail.`
|
const deleteErrorMessage = `delete error. see ${LOG_PATH} for more detail.`
|
||||||
|
|
||||||
async function responseForGet ({ response }: { response: http.ServerResponse }) {
|
async function responseForGet({ response }: { response: http.ServerResponse }) {
|
||||||
response.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })
|
response.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })
|
||||||
const htmlContent = marked(markdownContent)
|
const htmlContent = marked(markdownContent)
|
||||||
response.write(htmlContent)
|
response.write(htmlContent)
|
||||||
response.end()
|
response.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
router.get('/', responseForGet)
|
router.get('/', responseForGet)
|
||||||
router.get('/upload', responseForGet)
|
router.get('/upload', responseForGet)
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
'/upload',
|
'/upload',
|
||||||
async ({
|
async ({
|
||||||
response,
|
response,
|
||||||
list = [],
|
list = [],
|
||||||
urlparams
|
urlparams
|
||||||
}: {
|
}: {
|
||||||
response: IHttpResponse
|
response: IHttpResponse
|
||||||
list?: string[]
|
list?: string[]
|
||||||
urlparams?: URLSearchParams
|
urlparams?: URLSearchParams
|
||||||
}): Promise<void> => {
|
}): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const picbed = urlparams?.get('picbed')
|
const picbed = urlparams?.get('picbed')
|
||||||
const passedKey = urlparams?.get('key')
|
const passedKey = urlparams?.get('key')
|
||||||
const serverKey = picgo.getConfig<string>(configPaths.settings.serverKey) || ''
|
const serverKey = picgo.getConfig<string>(configPaths.settings.serverKey) || ''
|
||||||
const useShortUrl = picgo.getConfig<boolean>(configPaths.settings.useShortUrl)
|
const useShortUrl = picgo.getConfig<boolean>(configPaths.settings.useShortUrl)
|
||||||
if (serverKey && passedKey !== serverKey) {
|
if (serverKey && passedKey !== serverKey) {
|
||||||
handleResponse({
|
handleResponse({
|
||||||
response,
|
response,
|
||||||
body: {
|
body: {
|
||||||
success: false,
|
success: false,
|
||||||
message: 'server key is uncorrect'
|
message: 'server key is uncorrect'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let currentPicBedType = ''
|
let currentPicBedType = ''
|
||||||
let currentPicBedConfig = {} as IStringKeyMap
|
let currentPicBedConfig = {} as IStringKeyMap
|
||||||
let currentPicBedConfigId = ''
|
let currentPicBedConfigId = ''
|
||||||
let needRestore = false
|
let needRestore = false
|
||||||
if (picbed) {
|
if (picbed) {
|
||||||
const currentPicBed = picgo.getConfig<IStringKeyMap>('picBed') || ({} as IStringKeyMap)
|
const currentPicBed = picgo.getConfig<IStringKeyMap>('picBed') || ({} as IStringKeyMap)
|
||||||
currentPicBedType = currentPicBed.uploader || currentPicBed.current || 'smms'
|
currentPicBedType = currentPicBed.uploader || currentPicBed.current || 'smms'
|
||||||
currentPicBedConfig = currentPicBed[currentPicBedType] || ({} as IStringKeyMap)
|
currentPicBedConfig = currentPicBed[currentPicBedType] || ({} as IStringKeyMap)
|
||||||
currentPicBedConfigId = currentPicBedConfig._id
|
currentPicBedConfigId = currentPicBedConfig._id
|
||||||
const configName = urlparams?.get('configName') || currentPicBed[picbed]?._configName
|
const configName = urlparams?.get('configName') || currentPicBed[picbed]?._configName
|
||||||
if (picbed === currentPicBedType && configName === currentPicBedConfig._configName) {
|
if (picbed === currentPicBedType && configName === currentPicBedConfig._configName) {
|
||||||
// do nothing
|
// do nothing
|
||||||
} else {
|
} else {
|
||||||
needRestore = true
|
needRestore = true
|
||||||
const picBeds = picgo.getConfig<IStringKeyMap>('uploader')
|
const picBeds = picgo.getConfig<IStringKeyMap>('uploader')
|
||||||
const currentPicBedList = picBeds?.[picbed]?.configList
|
const currentPicBedList = picBeds?.[picbed]?.configList
|
||||||
if (currentPicBedList) {
|
if (currentPicBedList) {
|
||||||
const currentConfig = currentPicBedList?.find((item: any) => item._configName === configName)
|
const currentConfig = currentPicBedList?.find((item: any) => item._configName === configName)
|
||||||
if (currentConfig) {
|
if (currentConfig) {
|
||||||
changeCurrentUploader(picbed, currentConfig, currentConfig._id)
|
changeCurrentUploader(picbed, currentConfig, currentConfig._id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (list.length === 0) {
|
if (list.length === 0) {
|
||||||
// upload with clipboard
|
// upload with clipboard
|
||||||
logger.info('[PicList Server] upload clipboard file')
|
logger.info('[PicList Server] upload clipboard file')
|
||||||
const result = await uploadClipboardFiles()
|
const result = await uploadClipboardFiles()
|
||||||
const res = useShortUrl ? result.fullResult.shortUrl || result.url : result.url
|
const res = useShortUrl ? result.fullResult.shortUrl || result.url : result.url
|
||||||
const fullResult = result.fullResult
|
const fullResult = result.fullResult
|
||||||
fullResult.imgUrl = useShortUrl ? fullResult.shortUrl || fullResult.imgUrl : fullResult.imgUrl
|
fullResult.imgUrl = useShortUrl ? fullResult.shortUrl || fullResult.imgUrl : fullResult.imgUrl
|
||||||
logger.info('[PicList Server] upload result:', res)
|
logger.info('[PicList Server] upload result:', res)
|
||||||
if (res) {
|
if (res) {
|
||||||
const treatedFullResult = {
|
const treatedFullResult = {
|
||||||
isEncrypted: 1,
|
isEncrypted: 1,
|
||||||
EncryptedData: new AESHelper().encrypt(JSON.stringify(fullResult)),
|
EncryptedData: new AESHelper().encrypt(JSON.stringify(fullResult)),
|
||||||
...fullResult
|
...fullResult
|
||||||
}
|
}
|
||||||
delete treatedFullResult.config
|
delete treatedFullResult.config
|
||||||
handleResponse({
|
handleResponse({
|
||||||
response,
|
response,
|
||||||
body: {
|
body: {
|
||||||
success: true,
|
success: true,
|
||||||
result: [res],
|
result: [res],
|
||||||
fullResult: [treatedFullResult]
|
fullResult: [treatedFullResult]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
handleResponse({
|
handleResponse({
|
||||||
response,
|
response,
|
||||||
body: {
|
body: {
|
||||||
success: false,
|
success: false,
|
||||||
message: errorMessage
|
message: errorMessage
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.info('[PicList Server] upload files in list')
|
logger.info('[PicList Server] upload files in list')
|
||||||
// upload with files
|
// upload with files
|
||||||
const pathList = list.map(item => {
|
const pathList = list.map(item => {
|
||||||
return {
|
return {
|
||||||
path: item
|
path: item
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const win = windowManager.getAvailableWindow()
|
const win = windowManager.getAvailableWindow()
|
||||||
const result = await uploadChoosedFiles(win.webContents, pathList)
|
const result = await uploadChoosedFiles(win.webContents, pathList)
|
||||||
const res = result.map(item => {
|
const res = result.map(item => {
|
||||||
return useShortUrl ? item.fullResult.shortUrl || item.url : item.url
|
return useShortUrl ? item.fullResult.shortUrl || item.url : item.url
|
||||||
})
|
})
|
||||||
const fullResult = result.map((item: any) => {
|
const fullResult = result.map((item: any) => {
|
||||||
const treatedItem = {
|
const treatedItem = {
|
||||||
isEncrypted: 1,
|
isEncrypted: 1,
|
||||||
EncryptedData: new AESHelper().encrypt(JSON.stringify(item.fullResult)),
|
EncryptedData: new AESHelper().encrypt(JSON.stringify(item.fullResult)),
|
||||||
...item.fullResult
|
...item.fullResult
|
||||||
}
|
}
|
||||||
delete treatedItem.config
|
delete treatedItem.config
|
||||||
treatedItem.imgUrl = useShortUrl ? treatedItem.shortUrl || treatedItem.imgUrl : treatedItem.imgUrl
|
treatedItem.imgUrl = useShortUrl ? treatedItem.shortUrl || treatedItem.imgUrl : treatedItem.imgUrl
|
||||||
return treatedItem
|
return treatedItem
|
||||||
})
|
})
|
||||||
logger.info('[PicList Server] upload result', res.join(' ; '))
|
logger.info('[PicList Server] upload result', res.join(' ; '))
|
||||||
if (res.length) {
|
if (res.length) {
|
||||||
handleResponse({
|
handleResponse({
|
||||||
response,
|
response,
|
||||||
body: {
|
body: {
|
||||||
success: true,
|
success: true,
|
||||||
result: res,
|
result: res,
|
||||||
fullResult
|
fullResult
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
handleResponse({
|
handleResponse({
|
||||||
response,
|
response,
|
||||||
body: {
|
body: {
|
||||||
success: false,
|
success: false,
|
||||||
message: errorMessage
|
message: errorMessage
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fs.emptyDirSync(serverTempDir)
|
fs.emptyDirSync(serverTempDir)
|
||||||
if (needRestore) {
|
if (needRestore) {
|
||||||
changeCurrentUploader(currentPicBedType, currentPicBedConfig, currentPicBedConfigId)
|
changeCurrentUploader(currentPicBedType, currentPicBedConfig, currentPicBedConfigId)
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
handleResponse({
|
handleResponse({
|
||||||
response,
|
response,
|
||||||
body: {
|
body: {
|
||||||
success: false,
|
success: false,
|
||||||
message: errorMessage
|
message: errorMessage
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
'/delete',
|
'/delete',
|
||||||
async ({ response, list = [] }: { response: IHttpResponse; list?: IStringKeyMap[] }): Promise<void> => {
|
async ({ response, list = [] }: { response: IHttpResponse; list?: IStringKeyMap[] }): Promise<void> => {
|
||||||
if (list.length === 0) {
|
if (list.length === 0) {
|
||||||
handleResponse({
|
handleResponse({
|
||||||
response,
|
response,
|
||||||
body: {
|
body: {
|
||||||
success: false,
|
success: false,
|
||||||
message: 'no file to delete'
|
message: 'no file to delete'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const aesHelper = new AESHelper()
|
const aesHelper = new AESHelper()
|
||||||
const treatList = list.map(item => {
|
const treatList = list.map(item => {
|
||||||
if (!item.isEncrypted) return item
|
if (!item.isEncrypted) return item
|
||||||
return JSON.parse(aesHelper.decrypt(item.EncryptedData))
|
return JSON.parse(aesHelper.decrypt(item.EncryptedData))
|
||||||
})
|
})
|
||||||
const result = await deleteChoosedFiles(treatList)
|
const result = await deleteChoosedFiles(treatList)
|
||||||
const successCount = result.filter(item => item).length
|
const successCount = result.filter(item => item).length
|
||||||
const failCount = result.length - successCount
|
const failCount = result.length - successCount
|
||||||
handleResponse({
|
handleResponse({
|
||||||
response,
|
response,
|
||||||
body: {
|
body: {
|
||||||
success: !!successCount,
|
success: !!successCount,
|
||||||
message: successCount ? `delete success: ${successCount}, fail: ${failCount}` : deleteErrorMessage
|
message: successCount ? `delete success: ${successCount}, fail: ${failCount}` : deleteErrorMessage
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
handleResponse({
|
handleResponse({
|
||||||
response,
|
response,
|
||||||
body: {
|
body: {
|
||||||
success: false,
|
success: false,
|
||||||
message: deleteErrorMessage
|
message: deleteErrorMessage
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
router.any('/heartbeat', async ({ response }: { response: IHttpResponse }) => {
|
router.any('/heartbeat', async ({ response }: { response: IHttpResponse }) => {
|
||||||
handleResponse({
|
handleResponse({
|
||||||
response,
|
response,
|
||||||
body: {
|
body: {
|
||||||
success: true,
|
success: true,
|
||||||
result: 'alive'
|
result: 'alive'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { configPaths } from '~/utils/configPaths'
|
|||||||
|
|
||||||
const defaultPath = process.platform === 'win32' ? 'C:\\Users' : '/'
|
const defaultPath = process.platform === 'win32' ? 'C:\\Users' : '/'
|
||||||
|
|
||||||
function generateDirectoryListingHtml (files: any[], requestPath: any) {
|
function generateDirectoryListingHtml(files: any[], requestPath: any) {
|
||||||
let html = '<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body><h1>Directory Listing</h1><ul>'
|
let html = '<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body><h1>Directory Listing</h1><ul>'
|
||||||
files.forEach((file: string) => {
|
files.forEach((file: string) => {
|
||||||
const filePath = path.join(requestPath, file)
|
const filePath = path.join(requestPath, file)
|
||||||
@@ -21,7 +21,7 @@ function generateDirectoryListingHtml (files: any[], requestPath: any) {
|
|||||||
return html
|
return html
|
||||||
}
|
}
|
||||||
|
|
||||||
function serveDirectory (res: http.ServerResponse, filePath: fs.PathLike, requestPath: any) {
|
function serveDirectory(res: http.ServerResponse, filePath: fs.PathLike, requestPath: any) {
|
||||||
fs.readdir(filePath, (err, files) => {
|
fs.readdir(filePath, (err, files) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
res.writeHead(500)
|
res.writeHead(500)
|
||||||
@@ -33,7 +33,7 @@ function serveDirectory (res: http.ServerResponse, filePath: fs.PathLike, reques
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function serveFile (res: http.ServerResponse, filePath: fs.PathLike) {
|
function serveFile(res: http.ServerResponse, filePath: fs.PathLike) {
|
||||||
const readStream = fs.createReadStream(filePath)
|
const readStream = fs.createReadStream(filePath)
|
||||||
readStream.pipe(res)
|
readStream.pipe(res)
|
||||||
readStream.on('error', () => {
|
readStream.on('error', () => {
|
||||||
@@ -46,12 +46,12 @@ class WebServer {
|
|||||||
#server!: http.Server
|
#server!: http.Server
|
||||||
#config!: IStringKeyMap
|
#config!: IStringKeyMap
|
||||||
|
|
||||||
constructor () {
|
constructor() {
|
||||||
this.loadConfig()
|
this.loadConfig()
|
||||||
this.initServer()
|
this.initServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
loadConfig (): void {
|
loadConfig(): void {
|
||||||
this.#config = {
|
this.#config = {
|
||||||
enableWebServer: picgo.getConfig<boolean>(configPaths.settings.enableWebServer) || false,
|
enableWebServer: picgo.getConfig<boolean>(configPaths.settings.enableWebServer) || false,
|
||||||
webServerHost: picgo.getConfig<string>(configPaths.settings.webServerHost) || '0.0.0.0',
|
webServerHost: picgo.getConfig<string>(configPaths.settings.webServerHost) || '0.0.0.0',
|
||||||
@@ -60,7 +60,7 @@ class WebServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initServer (): void {
|
initServer(): void {
|
||||||
this.#server = http.createServer((req, res) => {
|
this.#server = http.createServer((req, res) => {
|
||||||
const requestPath = req.url?.split('?')[0]
|
const requestPath = req.url?.split('?')[0]
|
||||||
const filePath = path.join(this.#config.webServerPath, decodeURIComponent(requestPath || ''))
|
const filePath = path.join(this.#config.webServerPath, decodeURIComponent(requestPath || ''))
|
||||||
@@ -79,7 +79,7 @@ class WebServer {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
start () {
|
start() {
|
||||||
if (this.#config.enableWebServer) {
|
if (this.#config.enableWebServer) {
|
||||||
this.#server
|
this.#server
|
||||||
.listen(
|
.listen(
|
||||||
@@ -99,13 +99,13 @@ class WebServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stop () {
|
stop() {
|
||||||
this.#server.close(() => {
|
this.#server.close(() => {
|
||||||
logger.info('Web server is stopped')
|
logger.info('Web server is stopped')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
restart () {
|
restart() {
|
||||||
this.stop()
|
this.stop()
|
||||||
this.loadConfig()
|
this.loadConfig()
|
||||||
this.initServer()
|
this.initServer()
|
||||||
|
|||||||
@@ -1,75 +1,60 @@
|
|||||||
import crypto from 'node:crypto'
|
import crypto from 'node:crypto'
|
||||||
|
|
||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
|
|
||||||
import { configPaths } from '~/utils/configPaths'
|
import { configPaths } from '~/utils/configPaths'
|
||||||
|
|
||||||
export class AESHelper {
|
export class AESHelper {
|
||||||
static readonly #SALT = Buffer.from('a8b3c4d2e4f5098712345678feedc0de', 'hex')
|
static readonly #SALT = Buffer.from('a8b3c4d2e4f5098712345678feedc0de', 'hex')
|
||||||
static readonly #ITERATIONS = 100_000
|
static readonly #ITERATIONS = 100_000
|
||||||
static readonly #KEYLEN = 32
|
static readonly #KEYLEN = 32
|
||||||
static readonly #DIGEST = 'sha512' as const
|
static readonly #DIGEST = 'sha512' as const
|
||||||
static readonly #ALGO = 'aes-256-cbc'
|
static readonly #ALGO = 'aes-256-cbc'
|
||||||
static readonly #IV_LENGTH = 16
|
static readonly #IV_LENGTH = 16
|
||||||
static readonly #SEP = ':'
|
static readonly #SEP = ':'
|
||||||
|
|
||||||
static #keyCache = new Map<string, Buffer>()
|
static #keyCache = new Map<string, Buffer>()
|
||||||
|
|
||||||
readonly key: Buffer
|
readonly key: Buffer
|
||||||
|
|
||||||
constructor (password?: string) {
|
constructor(password?: string) {
|
||||||
const pwd =
|
const pwd = password ?? picgo.getConfig<string>(configPaths.settings.aesPassword) ?? 'aesPassword'
|
||||||
password ??
|
this.key = AESHelper.#deriveKey(pwd)
|
||||||
picgo.getConfig<string>(configPaths.settings.aesPassword) ??
|
}
|
||||||
'aesPassword'
|
|
||||||
this.key = AESHelper.#deriveKey(pwd)
|
static #deriveKey(password: string): Buffer {
|
||||||
}
|
const cached = this.#keyCache.get(password)
|
||||||
|
if (cached) return cached
|
||||||
static #deriveKey (password: string): Buffer {
|
const key = crypto.pbkdf2Sync(password, this.#SALT, this.#ITERATIONS, this.#KEYLEN, this.#DIGEST)
|
||||||
const cached = this.#keyCache.get(password)
|
this.#keyCache.set(password, key)
|
||||||
if (cached) return cached
|
return key
|
||||||
const key = crypto.pbkdf2Sync(
|
}
|
||||||
password,
|
|
||||||
this.#SALT,
|
encrypt(plainText: string): string {
|
||||||
this.#ITERATIONS,
|
const iv = crypto.randomBytes(AESHelper.#IV_LENGTH)
|
||||||
this.#KEYLEN,
|
const cipher = crypto.createCipheriv(AESHelper.#ALGO, this.key, iv)
|
||||||
this.#DIGEST
|
const encrypted = Buffer.concat([cipher.update(plainText, 'utf8'), cipher.final()])
|
||||||
)
|
return `${iv.toString('hex')}${AESHelper.#SEP}${encrypted.toString('hex')}`
|
||||||
this.#keyCache.set(password, key)
|
}
|
||||||
return key
|
|
||||||
}
|
decrypt(encryptedData: string): string {
|
||||||
|
if (!encryptedData) return '{}'
|
||||||
encrypt (plainText: string): string {
|
|
||||||
const iv = crypto.randomBytes(AESHelper.#IV_LENGTH)
|
const sepIndex = encryptedData.indexOf(AESHelper.#SEP)
|
||||||
const cipher = crypto.createCipheriv(AESHelper.#ALGO, this.key, iv)
|
if (sepIndex <= 0) return '{}'
|
||||||
const encrypted = Buffer.concat([
|
|
||||||
cipher.update(plainText, 'utf8'),
|
const ivHex = encryptedData.slice(0, sepIndex)
|
||||||
cipher.final()
|
const encryptedHex = encryptedData.slice(sepIndex + 1)
|
||||||
])
|
|
||||||
return `${iv.toString('hex')}${AESHelper.#SEP}${encrypted.toString('hex')}`
|
try {
|
||||||
}
|
const iv = Buffer.from(ivHex, 'hex')
|
||||||
|
if (iv.length !== AESHelper.#IV_LENGTH) return '{}'
|
||||||
decrypt (encryptedData: string): string {
|
|
||||||
if (!encryptedData) return '{}'
|
const decipher = crypto.createDecipheriv(AESHelper.#ALGO, this.key, iv)
|
||||||
|
const decrypted = Buffer.concat([decipher.update(Buffer.from(encryptedHex, 'hex')), decipher.final()])
|
||||||
const sepIndex = encryptedData.indexOf(AESHelper.#SEP)
|
return decrypted.toString('utf8')
|
||||||
if (sepIndex <= 0) return '{}'
|
} catch {
|
||||||
|
return '{}'
|
||||||
const ivHex = encryptedData.slice(0, sepIndex)
|
}
|
||||||
const encryptedHex = encryptedData.slice(sepIndex + 1)
|
}
|
||||||
|
}
|
||||||
try {
|
|
||||||
const iv = Buffer.from(ivHex, 'hex')
|
|
||||||
if (iv.length !== AESHelper.#IV_LENGTH) return '{}'
|
|
||||||
|
|
||||||
const decipher = crypto.createDecipheriv(AESHelper.#ALGO, this.key, iv)
|
|
||||||
const decrypted = Buffer.concat([
|
|
||||||
decipher.update(Buffer.from(encryptedHex, 'hex')),
|
|
||||||
decipher.final()
|
|
||||||
])
|
|
||||||
return decrypted.toString('utf8')
|
|
||||||
} catch {
|
|
||||||
return '{}'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const configPath = dbPathChecker()
|
|||||||
const CONFIG_DIR = path.dirname(configPath)
|
const CONFIG_DIR = path.dirname(configPath)
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||||
|
|
||||||
function beforeOpen () {
|
function beforeOpen() {
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
resolveMacWorkFlow()
|
resolveMacWorkFlow()
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ function beforeOpen () {
|
|||||||
resolveOtherI18nFiles()
|
resolveOtherI18nFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyFileOutsideOfElectronAsar (sourceInAsarArchive: string, destOutsideAsarArchive: string) {
|
function copyFileOutsideOfElectronAsar(sourceInAsarArchive: string, destOutsideAsarArchive: string) {
|
||||||
if (fs.existsSync(sourceInAsarArchive)) {
|
if (fs.existsSync(sourceInAsarArchive)) {
|
||||||
// file will be copied
|
// file will be copied
|
||||||
if (fs.statSync(sourceInAsarArchive).isFile()) {
|
if (fs.statSync(sourceInAsarArchive).isFile()) {
|
||||||
@@ -45,16 +45,21 @@ function copyFileOutsideOfElectronAsar (sourceInAsarArchive: string, destOutside
|
|||||||
/**
|
/**
|
||||||
* macOS 右键菜单
|
* macOS 右键菜单
|
||||||
*/
|
*/
|
||||||
function resolveMacWorkFlow () {
|
function resolveMacWorkFlow() {
|
||||||
const dest = `${os.homedir()}/Library/Services/Upload pictures with PicList.workflow`
|
const dest = `${os.homedir()}/Library/Services/Upload pictures with PicList.workflow`
|
||||||
try {
|
try {
|
||||||
copyFileOutsideOfElectronAsar(path.join(__dirname, '../../resources', 'Upload pictures with PicList.workflow').replace('app.asar', 'app.asar.unpacked'), dest)
|
copyFileOutsideOfElectronAsar(
|
||||||
|
path
|
||||||
|
.join(__dirname, '../../resources', 'Upload pictures with PicList.workflow')
|
||||||
|
.replace('app.asar', 'app.asar.unpacked'),
|
||||||
|
dest
|
||||||
|
)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function diffFilesAndUpdate (filePath1: string, filePath2: string) {
|
function diffFilesAndUpdate(filePath1: string, filePath2: string) {
|
||||||
try {
|
try {
|
||||||
const file1 = fs.existsSync(filePath1) && fs.readFileSync(filePath1)
|
const file1 = fs.existsSync(filePath1) && fs.readFileSync(filePath1)
|
||||||
const file2 = fs.existsSync(filePath1) && fs.readFileSync(filePath2)
|
const file2 = fs.existsSync(filePath1) && fs.readFileSync(filePath2)
|
||||||
@@ -71,7 +76,7 @@ function diffFilesAndUpdate (filePath1: string, filePath2: string) {
|
|||||||
/**
|
/**
|
||||||
* 初始化剪贴板生成图片的脚本
|
* 初始化剪贴板生成图片的脚本
|
||||||
*/
|
*/
|
||||||
function resolveClipboardImageGenerator () {
|
function resolveClipboardImageGenerator() {
|
||||||
const clipboardFiles = getClipboardFiles()
|
const clipboardFiles = getClipboardFiles()
|
||||||
if (!fs.pathExistsSync(path.join(CONFIG_DIR, 'windows10.ps1'))) {
|
if (!fs.pathExistsSync(path.join(CONFIG_DIR, 'windows10.ps1'))) {
|
||||||
clipboardFiles.forEach(item => {
|
clipboardFiles.forEach(item => {
|
||||||
@@ -84,7 +89,7 @@ function resolveClipboardImageGenerator () {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getClipboardFiles () {
|
function getClipboardFiles() {
|
||||||
const files = ['linux.sh', 'mac.applescript', 'windows.ps1', 'windows10.ps1', 'wsl.sh']
|
const files = ['linux.sh', 'mac.applescript', 'windows.ps1', 'windows10.ps1', 'wsl.sh']
|
||||||
|
|
||||||
return files.map(item => {
|
return files.map(item => {
|
||||||
@@ -99,7 +104,7 @@ function resolveClipboardImageGenerator () {
|
|||||||
/**
|
/**
|
||||||
* 初始化其他语言文件
|
* 初始化其他语言文件
|
||||||
*/
|
*/
|
||||||
function resolveOtherI18nFiles () {
|
function resolveOtherI18nFiles() {
|
||||||
const i18nFolder = path.join(CONFIG_DIR, 'i18n')
|
const i18nFolder = path.join(CONFIG_DIR, 'i18n')
|
||||||
if (!fs.pathExistsSync(i18nFolder)) {
|
if (!fs.pathExistsSync(i18nFolder)) {
|
||||||
fs.mkdirSync(i18nFolder)
|
fs.mkdirSync(i18nFolder)
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ class ClipboardWatcher extends EventEmitter {
|
|||||||
timer: NodeJS.Timeout | null
|
timer: NodeJS.Timeout | null
|
||||||
lastImageHash: string | null
|
lastImageHash: string | null
|
||||||
|
|
||||||
constructor () {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
this.lastImageHash = null
|
this.lastImageHash = null
|
||||||
this.timer = null
|
this.timer = null
|
||||||
}
|
}
|
||||||
|
|
||||||
startListening (watchDelay = 1000) {
|
startListening(watchDelay = 1000) {
|
||||||
this.stopListening(false)
|
this.stopListening(false)
|
||||||
|
|
||||||
this.timer = setInterval(() => {
|
this.timer = setInterval(() => {
|
||||||
@@ -34,7 +34,7 @@ class ClipboardWatcher extends EventEmitter {
|
|||||||
logger.info('Start to watch clipboard')
|
logger.info('Start to watch clipboard')
|
||||||
}
|
}
|
||||||
|
|
||||||
stopListening (isLog = true) {
|
stopListening(isLog = true) {
|
||||||
if (this.timer) {
|
if (this.timer) {
|
||||||
clearInterval(this.timer)
|
clearInterval(this.timer)
|
||||||
this.timer = null
|
this.timer = null
|
||||||
@@ -43,7 +43,7 @@ class ClipboardWatcher extends EventEmitter {
|
|||||||
isLog && logger.info('Stop to watch clipboard')
|
isLog && logger.info('Stop to watch clipboard')
|
||||||
}
|
}
|
||||||
|
|
||||||
getImageHash (image: NativeImage): string {
|
getImageHash(image: NativeImage): string {
|
||||||
const buffer = image.toBitmap()
|
const buffer = image.toBitmap()
|
||||||
return crypto.createHash('md5').update(buffer).digest('hex')
|
return crypto.createHash('md5').update(buffer).digest('hex')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,323 +1,323 @@
|
|||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
|
|
||||||
import db from '@core/datastore'
|
import db from '@core/datastore'
|
||||||
import logger from '@core/picgo/logger'
|
import logger from '@core/picgo/logger'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { clipboard, Notification, Tray } from 'electron'
|
import { clipboard, Notification, Tray } from 'electron'
|
||||||
import FormData from 'form-data'
|
import FormData from 'form-data'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import { isReactive, isRef, toRaw, unref } from 'vue'
|
import { isReactive, isRef, toRaw, unref } from 'vue'
|
||||||
|
|
||||||
import type { IHTTPProxy, IPrivateShowNotificationOption, IStringKeyMap } from '#/types/types'
|
import type { IHTTPProxy, IPrivateShowNotificationOption, IStringKeyMap } from '#/types/types'
|
||||||
import { configPaths } from '~/utils/configPaths'
|
import { configPaths } from '~/utils/configPaths'
|
||||||
import { IShortUrlServer } from '~/utils/enum'
|
import { IShortUrlServer } from '~/utils/enum'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get raw data from reactive or ref
|
* get raw data from reactive or ref
|
||||||
*/
|
*/
|
||||||
export const getRawData = (args: any): any => {
|
export const getRawData = (args: any): any => {
|
||||||
if (isRef(args)) return unref(args)
|
if (isRef(args)) return unref(args)
|
||||||
if (isReactive(args)) return toRaw(args)
|
if (isReactive(args)) return toRaw(args)
|
||||||
if (Array.isArray(args)) return args.map(getRawData)
|
if (Array.isArray(args)) return args.map(getRawData)
|
||||||
if (typeof args === 'object' && args !== null) {
|
if (typeof args === 'object' && args !== null) {
|
||||||
const data = {} as Record<string, any>
|
const data = {} as Record<string, any>
|
||||||
for (const key in args) {
|
for (const key in args) {
|
||||||
data[key] = getRawData(args[key])
|
data[key] = getRawData(args[key])
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
const getExtension = (fileName: string) => path.extname(fileName).slice(1)
|
const getExtension = (fileName: string) => path.extname(fileName).slice(1)
|
||||||
|
|
||||||
export const isImage = (fileName: string) =>
|
export const isImage = (fileName: string) =>
|
||||||
['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'ico', 'svg', 'avif'].includes(getExtension(fileName))
|
['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'ico', 'svg', 'avif'].includes(getExtension(fileName))
|
||||||
|
|
||||||
export let tray: Tray
|
export let tray: Tray
|
||||||
|
|
||||||
export const setTray = (t: Tray) => {
|
export const setTray = (t: Tray) => {
|
||||||
tray = t
|
tray = t
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getTray = () => tray
|
export const getTray = () => tray
|
||||||
|
|
||||||
export function setTrayToolTip (title: string): void {
|
export function setTrayToolTip(title: string): void {
|
||||||
if (tray) {
|
if (tray) {
|
||||||
tray.setToolTip(title)
|
tray.setToolTip(title)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const handleCopyUrl = (str: string): void => {
|
export const handleCopyUrl = (str: string): void => {
|
||||||
if (db.get(configPaths.settings.autoCopy) !== false) {
|
if (db.get(configPaths.settings.autoCopy) !== false) {
|
||||||
clipboard.writeText(str)
|
clipboard.writeText(str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* show notification
|
* show notification
|
||||||
* @param options
|
* @param options
|
||||||
*/
|
*/
|
||||||
export const showNotification = (
|
export const showNotification = (
|
||||||
options: IPrivateShowNotificationOption = {
|
options: IPrivateShowNotificationOption = {
|
||||||
title: '',
|
title: '',
|
||||||
body: '',
|
body: '',
|
||||||
clickToCopy: false,
|
clickToCopy: false,
|
||||||
copyContent: '',
|
copyContent: '',
|
||||||
clickFn: () => {}
|
clickFn: () => {}
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
const notification = new Notification({
|
const notification = new Notification({
|
||||||
title: options.title,
|
title: options.title,
|
||||||
body: options.body
|
body: options.body
|
||||||
})
|
})
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (options.clickToCopy) {
|
if (options.clickToCopy) {
|
||||||
clipboard.writeText(options.copyContent || options.body)
|
clipboard.writeText(options.copyContent || options.body)
|
||||||
}
|
}
|
||||||
if (options.clickFn) {
|
if (options.clickFn) {
|
||||||
options.clickFn()
|
options.clickFn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notification.once('click', handleClick)
|
notification.once('click', handleClick)
|
||||||
notification.once('close', () => {
|
notification.once('close', () => {
|
||||||
notification.removeListener('click', handleClick)
|
notification.removeListener('click', handleClick)
|
||||||
})
|
})
|
||||||
notification.show()
|
notification.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* macOS public.file-url will get encoded file path,
|
* macOS public.file-url will get encoded file path,
|
||||||
* so we need to decode it
|
* so we need to decode it
|
||||||
*/
|
*/
|
||||||
export const ensureFilePath = (filePath: string, prefix = 'file://'): string => {
|
export const ensureFilePath = (filePath: string, prefix = 'file://'): string => {
|
||||||
filePath = filePath.replace(prefix, '')
|
filePath = filePath.replace(prefix, '')
|
||||||
if (fs.existsSync(filePath)) {
|
if (fs.existsSync(filePath)) {
|
||||||
return `${prefix}${filePath}`
|
return `${prefix}${filePath}`
|
||||||
}
|
}
|
||||||
filePath = decodeURIComponent(filePath)
|
filePath = decodeURIComponent(filePath)
|
||||||
if (fs.existsSync(filePath)) {
|
if (fs.existsSync(filePath)) {
|
||||||
return `${prefix}${filePath}`
|
return `${prefix}${filePath}`
|
||||||
}
|
}
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* for builtin clipboard to get image path from clipboard
|
* for builtin clipboard to get image path from clipboard
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getClipboardFilePath = (): string => {
|
export const getClipboardFilePath = (): string => {
|
||||||
// TODO: linux support
|
// TODO: linux support
|
||||||
const img = clipboard.readImage()
|
const img = clipboard.readImage()
|
||||||
const platform = process.platform
|
const platform = process.platform
|
||||||
|
|
||||||
if (!img.isEmpty() && platform === 'darwin') {
|
if (!img.isEmpty() && platform === 'darwin') {
|
||||||
let imgPath = clipboard.read('public.file-url') // will get file://xxx/xxx
|
let imgPath = clipboard.read('public.file-url') // will get file://xxx/xxx
|
||||||
imgPath = ensureFilePath(imgPath)
|
imgPath = ensureFilePath(imgPath)
|
||||||
return imgPath ? imgPath.replace('file://', '') : ''
|
return imgPath ? imgPath.replace('file://', '') : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
if (img.isEmpty() && platform === 'win32') {
|
if (img.isEmpty() && platform === 'win32') {
|
||||||
const imgPath = clipboard
|
const imgPath = clipboard
|
||||||
.readBuffer('FileNameW')
|
.readBuffer('FileNameW')
|
||||||
?.toString('ucs2')
|
?.toString('ucs2')
|
||||||
?.replace(RegExp(String.fromCharCode(0), 'g'), '')
|
?.replace(RegExp(String.fromCharCode(0), 'g'), '')
|
||||||
return imgPath || ''
|
return imgPath || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const c1nApi = 'https://c1n.cn/link/short'
|
const c1nApi = 'https://c1n.cn/link/short'
|
||||||
|
|
||||||
const createC1NShortUrl = async (url: string) => {
|
const createC1NShortUrl = async (url: string) => {
|
||||||
const c1nToken = db.get(configPaths.settings.c1nToken) || ''
|
const c1nToken = db.get(configPaths.settings.c1nToken) || ''
|
||||||
if (!c1nToken) {
|
if (!c1nToken) {
|
||||||
logger.warn('c1n token is not set')
|
logger.warn('c1n token is not set')
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
form.append('url', url)
|
form.append('url', url)
|
||||||
const res = await axios.post(c1nApi, form, {
|
const res = await axios.post(c1nApi, form, {
|
||||||
headers: {
|
headers: {
|
||||||
token: c1nToken
|
token: c1nToken
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (res.status >= 200 && res.status < 300 && res.data?.code === 0) {
|
if (res.status >= 200 && res.status < 300 && res.data?.code === 0) {
|
||||||
return res.data.data
|
return res.data.data
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
}
|
}
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
const createYOURLSShortLink = async (url: string) => {
|
const createYOURLSShortLink = async (url: string) => {
|
||||||
let domain = db.get(configPaths.settings.yourlsDomain) || ''
|
let domain = db.get(configPaths.settings.yourlsDomain) || ''
|
||||||
const signature = db.get(configPaths.settings.yourlsSignature) || ''
|
const signature = db.get(configPaths.settings.yourlsSignature) || ''
|
||||||
|
|
||||||
if (!domain || !signature) {
|
if (!domain || !signature) {
|
||||||
logger.warn('Yourls server or signature is not set')
|
logger.warn('Yourls server or signature is not set')
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
if (!/^https?:\/\//.test(domain)) {
|
if (!/^https?:\/\//.test(domain)) {
|
||||||
domain = `http://${domain}`
|
domain = `http://${domain}`
|
||||||
}
|
}
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
signature,
|
signature,
|
||||||
action: 'shorturl',
|
action: 'shorturl',
|
||||||
format: 'json',
|
format: 'json',
|
||||||
url
|
url
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const res = await axios.get(`${domain}/yourls-api.php?${params.toString()}`)
|
const res = await axios.get(`${domain}/yourls-api.php?${params.toString()}`)
|
||||||
if (res.data?.shorturl) {
|
if (res.data?.shorturl) {
|
||||||
return res.data.shorturl
|
return res.data.shorturl
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
if (e.response?.data?.message?.includes('already exists in database')) {
|
if (e.response?.data?.message?.includes('already exists in database')) {
|
||||||
return e.response.data.shorturl
|
return e.response.data.shorturl
|
||||||
}
|
}
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
const createShortUrlForCFWorker = async (url: string) => {
|
const createShortUrlForCFWorker = async (url: string) => {
|
||||||
let cfWorkerHost = db.get(configPaths.settings.cfWorkerHost) || ''
|
let cfWorkerHost = db.get(configPaths.settings.cfWorkerHost) || ''
|
||||||
cfWorkerHost = cfWorkerHost.replace(/\/$/, '')
|
cfWorkerHost = cfWorkerHost.replace(/\/$/, '')
|
||||||
if (!cfWorkerHost) {
|
if (!cfWorkerHost) {
|
||||||
logger.warn('CF Worker host is not set')
|
logger.warn('CF Worker host is not set')
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await axios.post(cfWorkerHost, { url })
|
const res = await axios.post(cfWorkerHost, { url })
|
||||||
if (res.data?.status === 200 && res.data?.key?.startsWith('/')) {
|
if (res.data?.status === 200 && res.data?.key?.startsWith('/')) {
|
||||||
return `${cfWorkerHost}${res.data.key}`
|
return `${cfWorkerHost}${res.data.key}`
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
const createShortUrlFromSink = async (url: string) => {
|
const createShortUrlFromSink = async (url: string) => {
|
||||||
let sinkDomain = db.get(configPaths.settings.sinkDomain) || ''
|
let sinkDomain = db.get(configPaths.settings.sinkDomain) || ''
|
||||||
const sinkToken = db.get(configPaths.settings.sinkToken) || ''
|
const sinkToken = db.get(configPaths.settings.sinkToken) || ''
|
||||||
if (!sinkDomain || !sinkToken) {
|
if (!sinkDomain || !sinkToken) {
|
||||||
logger.warn('Sink domain or token is not set')
|
logger.warn('Sink domain or token is not set')
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
if (!/^https?:\/\//.test(sinkDomain)) {
|
if (!/^https?:\/\//.test(sinkDomain)) {
|
||||||
sinkDomain = `http://${sinkDomain}`
|
sinkDomain = `http://${sinkDomain}`
|
||||||
}
|
}
|
||||||
if (sinkDomain.endsWith('/')) {
|
if (sinkDomain.endsWith('/')) {
|
||||||
sinkDomain = sinkDomain.slice(0, -1)
|
sinkDomain = sinkDomain.slice(0, -1)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const res = await axios.post(
|
const res = await axios.post(
|
||||||
`${sinkDomain}/api/link/create`,
|
`${sinkDomain}/api/link/create`,
|
||||||
{ url },
|
{ url },
|
||||||
{ headers: { Authorization: `Bearer ${sinkToken}` } }
|
{ headers: { Authorization: `Bearer ${sinkToken}` } }
|
||||||
)
|
)
|
||||||
if (res.data?.link?.slug) {
|
if (res.data?.link?.slug) {
|
||||||
return `${sinkDomain}/${res.data.link.slug}`
|
return `${sinkDomain}/${res.data.link.slug}`
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
}
|
}
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generateShortUrl = async (url: string) => {
|
export const generateShortUrl = async (url: string) => {
|
||||||
const server = db.get(configPaths.settings.shortUrlServer) || IShortUrlServer.C1N
|
const server = db.get(configPaths.settings.shortUrlServer) || IShortUrlServer.C1N
|
||||||
switch (server) {
|
switch (server) {
|
||||||
case IShortUrlServer.C1N:
|
case IShortUrlServer.C1N:
|
||||||
return createC1NShortUrl(url)
|
return createC1NShortUrl(url)
|
||||||
case IShortUrlServer.YOURLS:
|
case IShortUrlServer.YOURLS:
|
||||||
return createYOURLSShortLink(url)
|
return createYOURLSShortLink(url)
|
||||||
case IShortUrlServer.CFWORKER:
|
case IShortUrlServer.CFWORKER:
|
||||||
return createShortUrlForCFWorker(url)
|
return createShortUrlForCFWorker(url)
|
||||||
case IShortUrlServer.SINK:
|
case IShortUrlServer.SINK:
|
||||||
return createShortUrlFromSink(url)
|
return createShortUrlFromSink(url)
|
||||||
default:
|
default:
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isUrl = (url: string): boolean => {
|
export const isUrl = (url: string): boolean => {
|
||||||
try {
|
try {
|
||||||
return Boolean(new URL(url))
|
return Boolean(new URL(url))
|
||||||
} catch {
|
} catch {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isUrlEncode = (url: string): boolean => {
|
export const isUrlEncode = (url: string): boolean => {
|
||||||
url = url || ''
|
url = url || ''
|
||||||
try {
|
try {
|
||||||
return url !== decodeURI(url)
|
return url !== decodeURI(url)
|
||||||
} catch {
|
} catch {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const handleUrlEncode = (url: string): string => (isUrlEncode(url) ? url : encodeURI(url))
|
export const handleUrlEncode = (url: string): string => (isUrlEncode(url) ? url : encodeURI(url))
|
||||||
|
|
||||||
export const handleUrlEncodeWithSetting = (url: string) =>
|
export const handleUrlEncodeWithSetting = (url: string) =>
|
||||||
db.get(configPaths.settings.encodeOutputURL) ? handleUrlEncode(url) : url
|
db.get(configPaths.settings.encodeOutputURL) ? handleUrlEncode(url) : url
|
||||||
|
|
||||||
export const handleStreamlinePluginName = (name: string) => name.replace(/(@[^/]+\/)?picgo-plugin-/, '')
|
export const handleStreamlinePluginName = (name: string) => name.replace(/(@[^/]+\/)?picgo-plugin-/, '')
|
||||||
export const simpleClone = (obj: any) => JSON.parse(JSON.stringify(obj))
|
export const simpleClone = (obj: any) => JSON.parse(JSON.stringify(obj))
|
||||||
export const enforceNumber = (num: number | string) => (isNaN(+num) ? 0 : +num)
|
export const enforceNumber = (num: number | string) => (isNaN(+num) ? 0 : +num)
|
||||||
|
|
||||||
export const trimValues = <T extends IStringKeyMap>(
|
export const trimValues = <T extends IStringKeyMap>(
|
||||||
obj: T
|
obj: T
|
||||||
): { [K in keyof T]: T[K] extends string ? string : T[K] } => {
|
): { [K in keyof T]: T[K] extends string ? string : T[K] } => {
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(obj).map(([key, value]) => [key, typeof value === 'string' ? value.trim() : value])
|
Object.entries(obj).map(([key, value]) => [key, typeof value === 'string' ? value.trim() : value])
|
||||||
) as { [K in keyof T]: T[K] extends string ? string : T[K] }
|
) as { [K in keyof T]: T[K] extends string ? string : T[K] }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const formatEndpoint = (endpoint: string, sslEnabled: boolean): string => {
|
export const formatEndpoint = (endpoint: string, sslEnabled: boolean): string => {
|
||||||
const hasProtocol = /^https?:\/\//.test(endpoint)
|
const hasProtocol = /^https?:\/\//.test(endpoint)
|
||||||
if (!hasProtocol) {
|
if (!hasProtocol) {
|
||||||
return `${sslEnabled ? 'https' : 'http'}://${endpoint}`
|
return `${sslEnabled ? 'https' : 'http'}://${endpoint}`
|
||||||
}
|
}
|
||||||
return sslEnabled ? endpoint.replace(/^http:\/\//, 'https://') : endpoint.replace(/^https:\/\//, 'http://')
|
return sslEnabled ? endpoint.replace(/^http:\/\//, 'https://') : endpoint.replace(/^https:\/\//, 'http://')
|
||||||
}
|
}
|
||||||
|
|
||||||
export const formatHttpProxy = (
|
export const formatHttpProxy = (
|
||||||
proxy: string | undefined,
|
proxy: string | undefined,
|
||||||
type: 'object' | 'string'
|
type: 'object' | 'string'
|
||||||
): IHTTPProxy | undefined | string => {
|
): IHTTPProxy | undefined | string => {
|
||||||
if (!proxy) return undefined
|
if (!proxy) return undefined
|
||||||
if (/^https?:\/\//.test(proxy)) {
|
if (/^https?:\/\//.test(proxy)) {
|
||||||
const { protocol, hostname, port } = new URL(proxy)
|
const { protocol, hostname, port } = new URL(proxy)
|
||||||
return type === 'string'
|
return type === 'string'
|
||||||
? `${protocol}//${hostname}:${port}`
|
? `${protocol}//${hostname}:${port}`
|
||||||
: {
|
: {
|
||||||
host: hostname,
|
host: hostname,
|
||||||
port: Number(port),
|
port: Number(port),
|
||||||
protocol: protocol.slice(0, -1)
|
protocol: protocol.slice(0, -1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const [host, port] = proxy.split(':')
|
const [host, port] = proxy.split(':')
|
||||||
return type === 'string'
|
return type === 'string'
|
||||||
? `http://${host}:${port}`
|
? `http://${host}:${port}`
|
||||||
: {
|
: {
|
||||||
host,
|
host,
|
||||||
port: port ? Number(port) : 80,
|
port: port ? Number(port) : 80,
|
||||||
protocol: 'http'
|
protocol: 'http'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function encodeFilePath (filePath: string) {
|
export function encodeFilePath(filePath: string) {
|
||||||
return filePath.replace(/\\/g, '/').split('/').map(encodeURIComponent).join('/')
|
return filePath.replace(/\\/g, '/').split('/').map(encodeURIComponent).join('/')
|
||||||
}
|
}
|
||||||
|
|
||||||
export const trimPath = (path: string) => path.replace(/^\/+|\/+$/g, '').replace(/\/+/g, '/')
|
export const trimPath = (path: string) => path.replace(/^\/+|\/+$/g, '').replace(/\/+/g, '/')
|
||||||
|
|||||||
@@ -1,188 +1,206 @@
|
|||||||
import type { IBuildInCompressOptions, IBuildInWaterMarkOptions } from 'piclist'
|
import type { IBuildInCompressOptions, IBuildInWaterMarkOptions } from 'piclist'
|
||||||
|
|
||||||
import type { IAliYunConfig, IAwsS3PListUserConfig, IGitHubConfig, IImgurConfig, ILocalConfig, ILskyConfig, IPicBedType, IQiniuConfig, IServerConfig, ISftpPlistConfig, IShortKeyConfig, ISMMSConfig, ISyncConfig, ITcYunConfig, IUploaderConfig, IUpYunConfig, IWebdavPlistConfig } from '#/types/types'
|
import type {
|
||||||
|
IAliYunConfig,
|
||||||
export type manualPageOpenType = 'window' | 'browser'
|
IAwsS3PListUserConfig,
|
||||||
|
IGitHubConfig,
|
||||||
interface IPicGoPlugins {
|
IImgurConfig,
|
||||||
[key: `picgo-plugin-${string}`]: boolean
|
ILocalConfig,
|
||||||
}
|
ILskyConfig,
|
||||||
|
IPicBedType,
|
||||||
export interface IConfigStruct {
|
IQiniuConfig,
|
||||||
picBed: {
|
IServerConfig,
|
||||||
uploader: string
|
ISftpPlistConfig,
|
||||||
current?: string
|
IShortKeyConfig,
|
||||||
smms?: ISMMSConfig
|
ISMMSConfig,
|
||||||
qiniu?: IQiniuConfig
|
ISyncConfig,
|
||||||
upyun?: IUpYunConfig
|
ITcYunConfig,
|
||||||
tcyun?: ITcYunConfig
|
IUploaderConfig,
|
||||||
github?: IGitHubConfig
|
IUpYunConfig,
|
||||||
aliyun?: IAliYunConfig
|
IWebdavPlistConfig
|
||||||
imgur?: IImgurConfig
|
} from '#/types/types'
|
||||||
webdavplist?: IWebdavPlistConfig
|
|
||||||
local?: ILocalConfig
|
export type manualPageOpenType = 'window' | 'browser'
|
||||||
sftpplist?: ISftpPlistConfig
|
|
||||||
lskyplist?: ILskyConfig
|
interface IPicGoPlugins {
|
||||||
'aws-s3-plist': IAwsS3PListUserConfig
|
[key: `picgo-plugin-${string}`]: boolean
|
||||||
proxy?: string
|
}
|
||||||
transformer?: string
|
|
||||||
list: IPicBedType[]
|
export interface IConfigStruct {
|
||||||
[others: string]: any
|
picBed: {
|
||||||
}
|
uploader: string
|
||||||
settings: {
|
current?: string
|
||||||
shortKey: {
|
smms?: ISMMSConfig
|
||||||
[key: string]: IShortKeyConfig
|
qiniu?: IQiniuConfig
|
||||||
}
|
upyun?: IUpYunConfig
|
||||||
logLevel: string[]
|
tcyun?: ITcYunConfig
|
||||||
logPath: string
|
github?: IGitHubConfig
|
||||||
logFileSizeLimit: number
|
aliyun?: IAliYunConfig
|
||||||
isAutoListenClipboard: boolean
|
imgur?: IImgurConfig
|
||||||
isListeningClipboard: boolean
|
webdavplist?: IWebdavPlistConfig
|
||||||
showUpdateTip: boolean
|
local?: ILocalConfig
|
||||||
miniWindowPosition: [number, number]
|
sftpplist?: ISftpPlistConfig
|
||||||
miniWindowOntop: boolean
|
lskyplist?: ILskyConfig
|
||||||
mainWindowWidth: number
|
'aws-s3-plist': IAwsS3PListUserConfig
|
||||||
mainWindowHeight: number
|
proxy?: string
|
||||||
isHideDock: boolean
|
transformer?: string
|
||||||
autoCloseMiniWindow: boolean
|
list: IPicBedType[]
|
||||||
autoCloseMainWindow: boolean
|
[others: string]: any
|
||||||
isCustomMiniIcon: boolean
|
}
|
||||||
customMiniIcon: string
|
settings: {
|
||||||
startMode: string
|
shortKey: {
|
||||||
autoRename: boolean
|
[key: string]: IShortKeyConfig
|
||||||
deleteCloudFile: boolean
|
}
|
||||||
server: IServerConfig
|
logLevel: string[]
|
||||||
serverKey: string
|
logPath: string
|
||||||
pasteStyle: string
|
logFileSizeLimit: number
|
||||||
aesPassword: string
|
isAutoListenClipboard: boolean
|
||||||
rename: boolean
|
isListeningClipboard: boolean
|
||||||
sync: ISyncConfig
|
showUpdateTip: boolean
|
||||||
tempDirPath: string
|
miniWindowPosition: [number, number]
|
||||||
language: string
|
miniWindowOntop: boolean
|
||||||
customLink: string
|
mainWindowWidth: number
|
||||||
manualPageOpen: manualPageOpenType
|
mainWindowHeight: number
|
||||||
encodeOutputURL: boolean
|
isHideDock: boolean
|
||||||
useShortUrl: boolean
|
autoCloseMiniWindow: boolean
|
||||||
shortUrlServer: string
|
autoCloseMainWindow: boolean
|
||||||
c1nToken: string
|
isCustomMiniIcon: boolean
|
||||||
cfWorkerHost: string
|
customMiniIcon: string
|
||||||
yourlsDomain: string
|
startMode: string
|
||||||
yourlsSignature: string
|
autoRename: boolean
|
||||||
sinkDomain: string
|
deleteCloudFile: boolean
|
||||||
sinkToken: string
|
server: IServerConfig
|
||||||
isSilentNotice: boolean
|
serverKey: string
|
||||||
proxy: string
|
pasteStyle: string
|
||||||
registry: string
|
aesPassword: string
|
||||||
autoCopy: boolean
|
rename: boolean
|
||||||
enableWebServer: boolean
|
sync: ISyncConfig
|
||||||
webServerHost: string
|
tempDirPath: string
|
||||||
webServerPort: number
|
language: string
|
||||||
webServerPath: string
|
customLink: string
|
||||||
deleteLocalFile: boolean
|
manualPageOpen: manualPageOpenType
|
||||||
uploadResultNotification: boolean
|
encodeOutputURL: boolean
|
||||||
uploadNotification: boolean
|
useShortUrl: boolean
|
||||||
useBuiltinClipboard: boolean
|
shortUrlServer: string
|
||||||
autoStart: boolean
|
c1nToken: string
|
||||||
autoImport: boolean
|
cfWorkerHost: string
|
||||||
autoImportPicBed: string[]
|
yourlsDomain: string
|
||||||
}
|
yourlsSignature: string
|
||||||
needReload: boolean
|
sinkDomain: string
|
||||||
picgoPlugins: IPicGoPlugins
|
sinkToken: string
|
||||||
uploader: IUploaderConfig
|
isSilentNotice: boolean
|
||||||
buildIn: {
|
proxy: string
|
||||||
compress: IBuildInCompressOptions
|
registry: string
|
||||||
watermark: IBuildInWaterMarkOptions
|
autoCopy: boolean
|
||||||
rename: {
|
enableWebServer: boolean
|
||||||
enable: boolean
|
webServerHost: string
|
||||||
format: string
|
webServerPort: number
|
||||||
}
|
webServerPath: string
|
||||||
skipProcess: {
|
deleteLocalFile: boolean
|
||||||
skipProcessExtList: string
|
uploadResultNotification: boolean
|
||||||
}
|
uploadNotification: boolean
|
||||||
}
|
useBuiltinClipboard: boolean
|
||||||
debug: boolean
|
autoStart: boolean
|
||||||
PICGO_ENV: string
|
autoImport: boolean
|
||||||
}
|
autoImportPicBed: string[]
|
||||||
|
}
|
||||||
export const configPaths = {
|
needReload: boolean
|
||||||
picBed: {
|
picgoPlugins: IPicGoPlugins
|
||||||
current: 'picBed.current',
|
uploader: IUploaderConfig
|
||||||
uploader: 'picBed.uploader',
|
buildIn: {
|
||||||
secondUploader: 'picBed.secondUploader',
|
compress: IBuildInCompressOptions
|
||||||
secondUploaderId: 'picBed.secondUploaderId',
|
watermark: IBuildInWaterMarkOptions
|
||||||
secondUploaderConfig: 'picBed.secondUploaderConfig',
|
rename: {
|
||||||
proxy: 'picBed.proxy',
|
enable: boolean
|
||||||
transformer: 'picBed.transformer',
|
format: string
|
||||||
list: 'picBed.list'
|
}
|
||||||
},
|
skipProcess: {
|
||||||
settings: {
|
skipProcessExtList: string
|
||||||
shortKey: {
|
}
|
||||||
_path: 'settings.shortKey',
|
}
|
||||||
'picgo:upload': 'settings.shortKey[picgo:upload]'
|
debug: boolean
|
||||||
},
|
PICGO_ENV: string
|
||||||
logLevel: 'settings.logLevel',
|
}
|
||||||
logPath: 'settings.logPath',
|
|
||||||
logFileSizeLimit: 'settings.logFileSizeLimit',
|
export const configPaths = {
|
||||||
isAutoListenClipboard: 'settings.isAutoListenClipboard',
|
picBed: {
|
||||||
isListeningClipboard: 'settings.isListeningClipboard',
|
current: 'picBed.current',
|
||||||
showUpdateTip: 'settings.showUpdateTip',
|
uploader: 'picBed.uploader',
|
||||||
miniWindowPosition: 'settings.miniWindowPosition',
|
secondUploader: 'picBed.secondUploader',
|
||||||
miniWindowOntop: 'settings.miniWindowOntop',
|
secondUploaderId: 'picBed.secondUploaderId',
|
||||||
isHideDock: 'settings.isHideDock',
|
secondUploaderConfig: 'picBed.secondUploaderConfig',
|
||||||
mainWindowWidth: 'settings.mainWindowWidth',
|
proxy: 'picBed.proxy',
|
||||||
mainWindowHeight: 'settings.mainWindowHeight',
|
transformer: 'picBed.transformer',
|
||||||
autoCloseMiniWindow: 'settings.autoCloseMiniWindow',
|
list: 'picBed.list'
|
||||||
autoCloseMainWindow: 'settings.autoCloseMainWindow',
|
},
|
||||||
isCustomMiniIcon: 'settings.isCustomMiniIcon',
|
settings: {
|
||||||
customMiniIcon: 'settings.customMiniIcon',
|
shortKey: {
|
||||||
startMode: 'settings.startMode',
|
_path: 'settings.shortKey',
|
||||||
autoRename: 'settings.autoRename',
|
'picgo:upload': 'settings.shortKey[picgo:upload]'
|
||||||
deleteCloudFile: 'settings.deleteCloudFile',
|
},
|
||||||
server: 'settings.server',
|
logLevel: 'settings.logLevel',
|
||||||
serverKey: 'settings.serverKey',
|
logPath: 'settings.logPath',
|
||||||
pasteStyle: 'settings.pasteStyle',
|
logFileSizeLimit: 'settings.logFileSizeLimit',
|
||||||
aesPassword: 'settings.aesPassword',
|
isAutoListenClipboard: 'settings.isAutoListenClipboard',
|
||||||
rename: 'settings.rename',
|
isListeningClipboard: 'settings.isListeningClipboard',
|
||||||
sync: 'settings.sync',
|
showUpdateTip: 'settings.showUpdateTip',
|
||||||
tempDirPath: 'settings.tempDirPath',
|
miniWindowPosition: 'settings.miniWindowPosition',
|
||||||
language: 'settings.language',
|
miniWindowOntop: 'settings.miniWindowOntop',
|
||||||
customLink: 'settings.customLink',
|
isHideDock: 'settings.isHideDock',
|
||||||
manualPageOpen: 'settings.manualPageOpen',
|
mainWindowWidth: 'settings.mainWindowWidth',
|
||||||
encodeOutputURL: 'settings.encodeOutputURL',
|
mainWindowHeight: 'settings.mainWindowHeight',
|
||||||
useShortUrl: 'settings.useShortUrl',
|
autoCloseMiniWindow: 'settings.autoCloseMiniWindow',
|
||||||
shortUrlServer: 'settings.shortUrlServer',
|
autoCloseMainWindow: 'settings.autoCloseMainWindow',
|
||||||
c1nToken: 'settings.c1nToken',
|
isCustomMiniIcon: 'settings.isCustomMiniIcon',
|
||||||
cfWorkerHost: 'settings.cfWorkerHost',
|
customMiniIcon: 'settings.customMiniIcon',
|
||||||
yourlsDomain: 'settings.yourlsDomain',
|
startMode: 'settings.startMode',
|
||||||
yourlsSignature: 'settings.yourlsSignature',
|
autoRename: 'settings.autoRename',
|
||||||
sinkDomain: 'settings.sinkDomain',
|
deleteCloudFile: 'settings.deleteCloudFile',
|
||||||
sinkToken: 'settings.sinkToken',
|
server: 'settings.server',
|
||||||
isSilentNotice: 'settings.isSilentNotice',
|
serverKey: 'settings.serverKey',
|
||||||
proxy: 'settings.proxy',
|
pasteStyle: 'settings.pasteStyle',
|
||||||
registry: 'settings.registry',
|
aesPassword: 'settings.aesPassword',
|
||||||
autoCopy: 'settings.autoCopy',
|
rename: 'settings.rename',
|
||||||
enableWebServer: 'settings.enableWebServer',
|
sync: 'settings.sync',
|
||||||
webServerHost: 'settings.webServerHost',
|
tempDirPath: 'settings.tempDirPath',
|
||||||
webServerPort: 'settings.webServerPort',
|
language: 'settings.language',
|
||||||
webServerPath: 'settings.webServerPath',
|
customLink: 'settings.customLink',
|
||||||
deleteLocalFile: 'settings.deleteLocalFile',
|
manualPageOpen: 'settings.manualPageOpen',
|
||||||
uploadResultNotification: 'settings.uploadResultNotification',
|
encodeOutputURL: 'settings.encodeOutputURL',
|
||||||
uploadNotification: 'settings.uploadNotification',
|
useShortUrl: 'settings.useShortUrl',
|
||||||
useBuiltinClipboard: 'settings.useBuiltinClipboard',
|
shortUrlServer: 'settings.shortUrlServer',
|
||||||
autoStart: 'settings.autoStart',
|
c1nToken: 'settings.c1nToken',
|
||||||
autoImport: 'settings.autoImport',
|
cfWorkerHost: 'settings.cfWorkerHost',
|
||||||
autoImportPicBed: 'settings.autoImportPicBed',
|
yourlsDomain: 'settings.yourlsDomain',
|
||||||
enableSecondUploader: 'settings.enableSecondUploader'
|
yourlsSignature: 'settings.yourlsSignature',
|
||||||
},
|
sinkDomain: 'settings.sinkDomain',
|
||||||
needReload: 'needReload',
|
sinkToken: 'settings.sinkToken',
|
||||||
picgoPlugins: 'picgoPlugins',
|
isSilentNotice: 'settings.isSilentNotice',
|
||||||
uploader: 'uploader',
|
proxy: 'settings.proxy',
|
||||||
buildIn: {
|
registry: 'settings.registry',
|
||||||
compress: 'buildIn.compress',
|
autoCopy: 'settings.autoCopy',
|
||||||
watermark: 'buildIn.watermark',
|
enableWebServer: 'settings.enableWebServer',
|
||||||
rename: 'buildIn.rename',
|
webServerHost: 'settings.webServerHost',
|
||||||
skipProcess: 'buildIn.skipProcess'
|
webServerPort: 'settings.webServerPort',
|
||||||
},
|
webServerPath: 'settings.webServerPath',
|
||||||
debug: 'debug',
|
deleteLocalFile: 'settings.deleteLocalFile',
|
||||||
PICGO_ENV: 'PICGO_ENV'
|
uploadResultNotification: 'settings.uploadResultNotification',
|
||||||
}
|
uploadNotification: 'settings.uploadNotification',
|
||||||
|
useBuiltinClipboard: 'settings.useBuiltinClipboard',
|
||||||
|
autoStart: 'settings.autoStart',
|
||||||
|
autoImport: 'settings.autoImport',
|
||||||
|
autoImportPicBed: 'settings.autoImportPicBed',
|
||||||
|
enableSecondUploader: 'settings.enableSecondUploader'
|
||||||
|
},
|
||||||
|
needReload: 'needReload',
|
||||||
|
picgoPlugins: 'picgoPlugins',
|
||||||
|
uploader: 'uploader',
|
||||||
|
buildIn: {
|
||||||
|
compress: 'buildIn.compress',
|
||||||
|
watermark: 'buildIn.watermark',
|
||||||
|
rename: 'buildIn.rename',
|
||||||
|
skipProcess: 'buildIn.skipProcess'
|
||||||
|
},
|
||||||
|
debug: 'debug',
|
||||||
|
PICGO_ENV: 'PICGO_ENV'
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,98 +1,98 @@
|
|||||||
import crypto from 'node:crypto'
|
import crypto from 'node:crypto'
|
||||||
import http, { AgentOptions } from 'node:http'
|
import http, { AgentOptions } from 'node:http'
|
||||||
import https from 'node:https'
|
import https from 'node:https'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import querystring from 'node:querystring'
|
import querystring from 'node:querystring'
|
||||||
|
|
||||||
import type { S3ClientConfig } from '@aws-sdk/client-s3'
|
import type { S3ClientConfig } from '@aws-sdk/client-s3'
|
||||||
import { DeleteObjectCommand, S3Client } from '@aws-sdk/client-s3'
|
import { DeleteObjectCommand, S3Client } from '@aws-sdk/client-s3'
|
||||||
import logger from '@core/picgo/logger'
|
import logger from '@core/picgo/logger'
|
||||||
import { NodeHttpHandler } from '@smithy/node-http-handler'
|
import { NodeHttpHandler } from '@smithy/node-http-handler'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import type { ISftpPlistConfig } from 'piclist'
|
import type { ISftpPlistConfig } from 'piclist'
|
||||||
|
|
||||||
import type { IObj, IStringKeyMap } from '#/types/types'
|
import type { IObj, IStringKeyMap } from '#/types/types'
|
||||||
import { getAgent } from '~/manage/utils/common'
|
import { getAgent } from '~/manage/utils/common'
|
||||||
import SSHClient from '~/utils/sshClient'
|
import SSHClient from '~/utils/sshClient'
|
||||||
|
|
||||||
interface DogecloudTokenFull {
|
interface DogecloudTokenFull {
|
||||||
Credentials: {
|
Credentials: {
|
||||||
accessKeyId: string
|
accessKeyId: string
|
||||||
secretAccessKey: string
|
secretAccessKey: string
|
||||||
sessionToken: string
|
sessionToken: string
|
||||||
}
|
}
|
||||||
ExpiredAt: number
|
ExpiredAt: number
|
||||||
Buckets: {
|
Buckets: {
|
||||||
name: string
|
name: string
|
||||||
s3Bucket: string
|
s3Bucket: string
|
||||||
s3Endpoint: string
|
s3Endpoint: string
|
||||||
}[]
|
}[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const dogeRegionMap: IStringKeyMap = {
|
const dogeRegionMap: IStringKeyMap = {
|
||||||
'ap-shanghai': '0',
|
'ap-shanghai': '0',
|
||||||
'ap-beijing': '1',
|
'ap-beijing': '1',
|
||||||
'ap-guangzhou': '2',
|
'ap-guangzhou': '2',
|
||||||
'ap-chengdu': '3'
|
'ap-chengdu': '3'
|
||||||
}
|
}
|
||||||
|
|
||||||
async function dogecloudApi (
|
async function dogecloudApi(
|
||||||
apiPath: string,
|
apiPath: string,
|
||||||
data = {},
|
data = {},
|
||||||
jsonMode: boolean = false,
|
jsonMode: boolean = false,
|
||||||
accessKey: string,
|
accessKey: string,
|
||||||
secretKey: string
|
secretKey: string
|
||||||
) {
|
) {
|
||||||
const body = jsonMode ? JSON.stringify(data) : querystring.encode(data)
|
const body = jsonMode ? JSON.stringify(data) : querystring.encode(data)
|
||||||
const sign = crypto
|
const sign = crypto
|
||||||
.createHmac('sha1', secretKey)
|
.createHmac('sha1', secretKey)
|
||||||
.update(Buffer.from(apiPath + '\n' + body, 'utf8'))
|
.update(Buffer.from(apiPath + '\n' + body, 'utf8'))
|
||||||
.digest('hex')
|
.digest('hex')
|
||||||
const authorization = `TOKEN ${accessKey}:${sign}`
|
const authorization = `TOKEN ${accessKey}:${sign}`
|
||||||
try {
|
try {
|
||||||
const res = await axios.request({
|
const res = await axios.request({
|
||||||
url: `https://api.dogecloud.com${apiPath}`,
|
url: `https://api.dogecloud.com${apiPath}`,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: body,
|
data: body,
|
||||||
responseType: 'json',
|
responseType: 'json',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': jsonMode ? 'application/json' : 'application/x-www-form-urlencoded',
|
'Content-Type': jsonMode ? 'application/json' : 'application/x-www-form-urlencoded',
|
||||||
Authorization: authorization
|
Authorization: authorization
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (res.data.code !== 200) {
|
if (res.data.code !== 200) {
|
||||||
throw new Error('API Error')
|
throw new Error('API Error')
|
||||||
}
|
}
|
||||||
return res.data.data
|
return res.data.data
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
throw new Error('API Error')
|
throw new Error('API Error')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getDogeToken (accessKey: string, secretKey: string): Promise<IObj | DogecloudTokenFull> {
|
async function getDogeToken(accessKey: string, secretKey: string): Promise<IObj | DogecloudTokenFull> {
|
||||||
try {
|
try {
|
||||||
const data = await dogecloudApi(
|
const data = await dogecloudApi(
|
||||||
'/auth/tmp_token.json',
|
'/auth/tmp_token.json',
|
||||||
{
|
{
|
||||||
channel: 'OSS_FULL',
|
channel: 'OSS_FULL',
|
||||||
scopes: ['*']
|
scopes: ['*']
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
accessKey,
|
accessKey,
|
||||||
secretKey
|
secretKey
|
||||||
)
|
)
|
||||||
return data
|
return data
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeFileFromS3InMain (configMap: IStringKeyMap, dogeMode: boolean = false) {
|
export async function removeFileFromS3InMain(configMap: IStringKeyMap, dogeMode: boolean = false) {
|
||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
url: rawUrl,
|
url: rawUrl,
|
||||||
type,
|
type,
|
||||||
config: {
|
config: {
|
||||||
accessKeyID,
|
accessKeyID,
|
||||||
secretAccessKey,
|
secretAccessKey,
|
||||||
@@ -103,14 +103,14 @@ export async function removeFileFromS3InMain (configMap: IStringKeyMap, dogeMode
|
|||||||
proxy,
|
proxy,
|
||||||
urlPrefix
|
urlPrefix
|
||||||
}
|
}
|
||||||
} = configMap
|
} = configMap
|
||||||
let {
|
let {
|
||||||
imgUrl,
|
imgUrl,
|
||||||
config: { region }
|
config: { region }
|
||||||
} = configMap
|
} = configMap
|
||||||
if (type === 'aws-s3' || type === 'aws-s3-plist') {
|
if (type === 'aws-s3' || type === 'aws-s3-plist') {
|
||||||
imgUrl = rawUrl || imgUrl || ''
|
imgUrl = rawUrl || imgUrl || ''
|
||||||
}
|
}
|
||||||
let fileKey
|
let fileKey
|
||||||
if (urlPrefix && imgUrl.startsWith(urlPrefix)) {
|
if (urlPrefix && imgUrl.startsWith(urlPrefix)) {
|
||||||
const urlPrefixObj = new URL(urlPrefix)
|
const urlPrefixObj = new URL(urlPrefix)
|
||||||
@@ -126,159 +126,159 @@ export async function removeFileFromS3InMain (configMap: IStringKeyMap, dogeMode
|
|||||||
if (pathStyleAccess) {
|
if (pathStyleAccess) {
|
||||||
fileKey = fileKey.replace(/^[^/]+\//, '')
|
fileKey = fileKey.replace(/^[^/]+\//, '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const endpointUrl: string | undefined = endpoint
|
const endpointUrl: string | undefined = endpoint
|
||||||
? /^https?:\/\//.test(endpoint)
|
? /^https?:\/\//.test(endpoint)
|
||||||
? endpoint
|
? endpoint
|
||||||
: `http://${endpoint}`
|
: `http://${endpoint}`
|
||||||
: undefined
|
: undefined
|
||||||
if (endpointUrl && endpointUrl.includes('cloudflarestorage')) {
|
if (endpointUrl && endpointUrl.includes('cloudflarestorage')) {
|
||||||
region = region || 'auto'
|
region = region || 'auto'
|
||||||
}
|
}
|
||||||
const sslEnabled = endpointUrl ? endpointUrl.startsWith('https') : true
|
const sslEnabled = endpointUrl ? endpointUrl.startsWith('https') : true
|
||||||
const agent = getAgent(proxy, sslEnabled)
|
const agent = getAgent(proxy, sslEnabled)
|
||||||
const commonOptions: AgentOptions = {
|
const commonOptions: AgentOptions = {
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
keepAliveMsecs: 1000,
|
keepAliveMsecs: 1000,
|
||||||
scheduling: 'lifo' as 'lifo' | 'fifo' | undefined
|
scheduling: 'lifo' as 'lifo' | 'fifo' | undefined
|
||||||
}
|
}
|
||||||
const extraOptions = sslEnabled ? { rejectUnauthorized: !!rejectUnauthorized } : {}
|
const extraOptions = sslEnabled ? { rejectUnauthorized: !!rejectUnauthorized } : {}
|
||||||
const handler = sslEnabled
|
const handler = sslEnabled
|
||||||
? new NodeHttpHandler({
|
? new NodeHttpHandler({
|
||||||
httpsAgent: agent.https
|
httpsAgent: agent.https
|
||||||
? agent.https
|
? agent.https
|
||||||
: new https.Agent({
|
: new https.Agent({
|
||||||
...commonOptions,
|
...commonOptions,
|
||||||
...extraOptions
|
...extraOptions
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
: new NodeHttpHandler({
|
: new NodeHttpHandler({
|
||||||
httpAgent: agent.http
|
httpAgent: agent.http
|
||||||
? agent.http
|
? agent.http
|
||||||
: new http.Agent({
|
: new http.Agent({
|
||||||
...commonOptions,
|
...commonOptions,
|
||||||
...extraOptions
|
...extraOptions
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
const s3Options: S3ClientConfig = {
|
const s3Options: S3ClientConfig = {
|
||||||
credentials: {
|
credentials: {
|
||||||
accessKeyId: accessKeyID,
|
accessKeyId: accessKeyID,
|
||||||
secretAccessKey
|
secretAccessKey
|
||||||
},
|
},
|
||||||
endpoint: endpointUrl,
|
endpoint: endpointUrl,
|
||||||
tls: sslEnabled,
|
tls: sslEnabled,
|
||||||
forcePathStyle: pathStyleAccess,
|
forcePathStyle: pathStyleAccess,
|
||||||
region,
|
region,
|
||||||
requestHandler: handler
|
requestHandler: handler
|
||||||
}
|
}
|
||||||
if (dogeMode) {
|
if (dogeMode) {
|
||||||
s3Options.credentials = {
|
s3Options.credentials = {
|
||||||
accessKeyId: configMap.config.accessKeyID,
|
accessKeyId: configMap.config.accessKeyID,
|
||||||
secretAccessKey: configMap.config.secretAccessKey,
|
secretAccessKey: configMap.config.secretAccessKey,
|
||||||
sessionToken: configMap.config.sessionToken
|
sessionToken: configMap.config.sessionToken
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let result: any
|
let result: any
|
||||||
try {
|
try {
|
||||||
fileKey = decodeURIComponent(fileKey)
|
fileKey = decodeURIComponent(fileKey)
|
||||||
} catch (err: any) {}
|
} catch (err: any) {}
|
||||||
try {
|
try {
|
||||||
const client = new S3Client(s3Options)
|
const client = new S3Client(s3Options)
|
||||||
const command = new DeleteObjectCommand({
|
const command = new DeleteObjectCommand({
|
||||||
Bucket: bucketName,
|
Bucket: bucketName,
|
||||||
Key: fileKey
|
Key: fileKey
|
||||||
})
|
})
|
||||||
result = await client.send(command)
|
result = await client.send(command)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
s3Options.region = 'us-east-1'
|
s3Options.region = 'us-east-1'
|
||||||
const client = new S3Client(s3Options)
|
const client = new S3Client(s3Options)
|
||||||
const command = new DeleteObjectCommand({
|
const command = new DeleteObjectCommand({
|
||||||
Bucket: bucketName,
|
Bucket: bucketName,
|
||||||
Key: fileKey
|
Key: fileKey
|
||||||
})
|
})
|
||||||
result = await client.send(command)
|
result = await client.send(command)
|
||||||
}
|
}
|
||||||
return result.$metadata.httpStatusCode === 204
|
return result.$metadata.httpStatusCode === 204
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeFileFromDogeInMain (configMap: IStringKeyMap) {
|
export async function removeFileFromDogeInMain(configMap: IStringKeyMap) {
|
||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
config: { bucketName, AccessKey, SecretKey }
|
config: { bucketName, AccessKey, SecretKey }
|
||||||
} = configMap
|
} = configMap
|
||||||
const token = (await getDogeToken(AccessKey, SecretKey)) as DogecloudTokenFull
|
const token = (await getDogeToken(AccessKey, SecretKey)) as DogecloudTokenFull
|
||||||
const bucket = token.Buckets?.find(item => item.name === bucketName || item.s3Bucket === bucketName)
|
const bucket = token.Buckets?.find(item => item.name === bucketName || item.s3Bucket === bucketName)
|
||||||
const newConfigMap = { ...configMap }
|
const newConfigMap = { ...configMap }
|
||||||
newConfigMap.config = {
|
newConfigMap.config = {
|
||||||
...newConfigMap.config,
|
...newConfigMap.config,
|
||||||
accessKeyID: token.Credentials?.accessKeyId,
|
accessKeyID: token.Credentials?.accessKeyId,
|
||||||
secretAccessKey: token.Credentials?.secretAccessKey,
|
secretAccessKey: token.Credentials?.secretAccessKey,
|
||||||
sessionToken: token.Credentials?.sessionToken,
|
sessionToken: token.Credentials?.sessionToken,
|
||||||
endpoint: bucket?.s3Endpoint,
|
endpoint: bucket?.s3Endpoint,
|
||||||
region: dogeRegionMap[bucket?.s3Endpoint?.split('.')[1] || 'ap-shanghai'],
|
region: dogeRegionMap[bucket?.s3Endpoint?.split('.')[1] || 'ap-shanghai'],
|
||||||
bucketName: bucket?.s3Bucket
|
bucketName: bucket?.s3Bucket
|
||||||
}
|
}
|
||||||
return await removeFileFromS3InMain(newConfigMap, true)
|
return await removeFileFromS3InMain(newConfigMap, true)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createHuaweiAuthorization (
|
function createHuaweiAuthorization(
|
||||||
bucketName: string,
|
bucketName: string,
|
||||||
path: string,
|
path: string,
|
||||||
fileName: string,
|
fileName: string,
|
||||||
accessKey: string,
|
accessKey: string,
|
||||||
secretKey: string,
|
secretKey: string,
|
||||||
date: string = new Date().toUTCString()
|
date: string = new Date().toUTCString()
|
||||||
) {
|
) {
|
||||||
const strToSign = `DELETE\n\n\n${date}\n/${bucketName}${path}/${fileName}`
|
const strToSign = `DELETE\n\n\n${date}\n/${bucketName}${path}/${fileName}`
|
||||||
const singature = crypto.createHmac('sha1', secretKey).update(strToSign).digest('base64')
|
const singature = crypto.createHmac('sha1', secretKey).update(strToSign).digest('base64')
|
||||||
return `OBS ${accessKey}:${singature}`
|
return `OBS ${accessKey}:${singature}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeFileFromHuaweiInMain (configMap: IStringKeyMap) {
|
export async function removeFileFromHuaweiInMain(configMap: IStringKeyMap) {
|
||||||
const { fileName, config } = configMap
|
const { fileName, config } = configMap
|
||||||
const { accessKeyId, accessKeySecret, bucketName, endpoint } = config
|
const { accessKeyId, accessKeySecret, bucketName, endpoint } = config
|
||||||
let path = config.path || '/'
|
let path = config.path || '/'
|
||||||
path = `/${path.replace(/^\/+|\/+$/, '')}`
|
path = `/${path.replace(/^\/+|\/+$/, '')}`
|
||||||
path = path === '/' ? '' : path
|
path = path === '/' ? '' : path
|
||||||
const date = new Date().toUTCString()
|
const date = new Date().toUTCString()
|
||||||
const authorization = createHuaweiAuthorization(bucketName, path, fileName, accessKeyId, accessKeySecret, date)
|
const authorization = createHuaweiAuthorization(bucketName, path, fileName, accessKeyId, accessKeySecret, date)
|
||||||
try {
|
try {
|
||||||
const res = await axios.request({
|
const res = await axios.request({
|
||||||
url: `https://${bucketName}.${endpoint}${encodeURI(path)}/${encodeURIComponent(fileName)}`,
|
url: `https://${bucketName}.${endpoint}${encodeURI(path)}/${encodeURIComponent(fileName)}`,
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
responseType: 'json',
|
responseType: 'json',
|
||||||
headers: {
|
headers: {
|
||||||
Host: `${bucketName}.${endpoint}`,
|
Host: `${bucketName}.${endpoint}`,
|
||||||
Date: date,
|
Date: date,
|
||||||
Authorization: authorization
|
Authorization: authorization
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return res.status === 204
|
return res.status === 204
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
logger.error(error)
|
logger.error(error)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeFileFromSFTPInMain (config: ISftpPlistConfig, fileName: string) {
|
export async function removeFileFromSFTPInMain(config: ISftpPlistConfig, fileName: string) {
|
||||||
try {
|
try {
|
||||||
const client = SSHClient.instance
|
const client = SSHClient.instance
|
||||||
await client.connect(config)
|
await client.connect(config)
|
||||||
const uploadPath = `/${config.uploadPath || ''}/`.replace(/\/+/g, '/')
|
const uploadPath = `/${config.uploadPath || ''}/`.replace(/\/+/g, '/')
|
||||||
const remote = path.join(uploadPath, fileName)
|
const remote = path.join(uploadPath, fileName)
|
||||||
const deleteResult = await client.deleteFileSFTP(config, remote)
|
const deleteResult = await client.deleteFileSFTP(config, remote)
|
||||||
client.close()
|
client.close()
|
||||||
return deleteResult
|
return deleteResult
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
export const deleteLog = (fileName?: string, type?: string, isSuccess = true, msg?: string) => {
|
export const deleteLog = (fileName?: string, type?: string, isSuccess = true, msg?: string) => {
|
||||||
console.log(`Delete ${fileName} on ${type} ${isSuccess ? 'success' : 'failed'}, message: ${msg || ''}`)
|
console.log(`Delete ${fileName} on ${type} ${isSuccess ? 'success' : 'failed'}, message: ${msg || ''}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const deleteFailedLog = (fileName: string, type: string, error: any) => {
|
export const deleteFailedLog = (fileName: string, type: string, error: any) => {
|
||||||
deleteLog(fileName, type, false)
|
deleteLog(fileName, type, false)
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ const AUTH_KEY_VALUE_RE = /(\w+)=["']?([^'"]{1,10000})["']?/
|
|||||||
let NC = 0
|
let NC = 0
|
||||||
const NC_PAD = '00000000'
|
const NC_PAD = '00000000'
|
||||||
|
|
||||||
function md5 (text: crypto.BinaryLike) {
|
function md5(text: crypto.BinaryLike) {
|
||||||
return crypto.createHash('md5').update(text).digest('hex')
|
return crypto.createHash('md5').update(text).digest('hex')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function digestAuthHeader (
|
export function digestAuthHeader(
|
||||||
method: string,
|
method: string,
|
||||||
uri: string,
|
uri: string,
|
||||||
wwwAuthenticate: string,
|
wwwAuthenticate: string,
|
||||||
@@ -70,7 +70,7 @@ export function digestAuthHeader (
|
|||||||
return authstring
|
return authstring
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getAuthHeader (method: string, host: string, uri: string, username: string, password: string) {
|
export async function getAuthHeader(method: string, host: string, uri: string, username: string, password: string) {
|
||||||
try {
|
try {
|
||||||
await axios.get(`${host}${uri}`)
|
await axios.get(`${host}${uri}`)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
|||||||
@@ -1,242 +1,242 @@
|
|||||||
export const ILogType = {
|
export const ILogType = {
|
||||||
success: 'success',
|
success: 'success',
|
||||||
info: 'info',
|
info: 'info',
|
||||||
warn: 'warn',
|
warn: 'warn',
|
||||||
error: 'error'
|
error: 'error'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ICOREBuildInEvent = {
|
export const ICOREBuildInEvent = {
|
||||||
UPLOAD_PROGRESS: 'uploadProgress',
|
UPLOAD_PROGRESS: 'uploadProgress',
|
||||||
FAILED: 'failed',
|
FAILED: 'failed',
|
||||||
BEFORE_TRANSFORM: 'beforeTransform',
|
BEFORE_TRANSFORM: 'beforeTransform',
|
||||||
BEFORE_UPLOAD: 'beforeUpload',
|
BEFORE_UPLOAD: 'beforeUpload',
|
||||||
AFTER_UPLOAD: 'afterUpload',
|
AFTER_UPLOAD: 'afterUpload',
|
||||||
FINISHED: 'finished',
|
FINISHED: 'finished',
|
||||||
INSTALL: 'install',
|
INSTALL: 'install',
|
||||||
UNINSTALL: 'uninstall',
|
UNINSTALL: 'uninstall',
|
||||||
UPDATE: 'update',
|
UPDATE: 'update',
|
||||||
NOTIFICATION: 'notification',
|
NOTIFICATION: 'notification',
|
||||||
REMOVE: 'remove'
|
REMOVE: 'remove'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IPicGoHelperType = {
|
export const IPicGoHelperType = {
|
||||||
afterUploadPlugins: 'afterUploadPlugins',
|
afterUploadPlugins: 'afterUploadPlugins',
|
||||||
beforeTransformPlugins: 'beforeTransformPlugins',
|
beforeTransformPlugins: 'beforeTransformPlugins',
|
||||||
beforeUploadPlugins: 'beforeUploadPlugins',
|
beforeUploadPlugins: 'beforeUploadPlugins',
|
||||||
uploader: 'uploader',
|
uploader: 'uploader',
|
||||||
transformer: 'transformer'
|
transformer: 'transformer'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IPasteStyle = {
|
export const IPasteStyle = {
|
||||||
MARKDOWN: 'markdown',
|
MARKDOWN: 'markdown',
|
||||||
HTML: 'HTML',
|
HTML: 'HTML',
|
||||||
URL: 'URL',
|
URL: 'URL',
|
||||||
UBB: 'UBB',
|
UBB: 'UBB',
|
||||||
CUSTOM: 'Custom'
|
CUSTOM: 'Custom'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IWindowList = {
|
export const IWindowList = {
|
||||||
SETTING_WINDOW: 'SETTING_WINDOW',
|
SETTING_WINDOW: 'SETTING_WINDOW',
|
||||||
TRAY_WINDOW: 'TRAY_WINDOW',
|
TRAY_WINDOW: 'TRAY_WINDOW',
|
||||||
MINI_WINDOW: 'MINI_WINDOW',
|
MINI_WINDOW: 'MINI_WINDOW',
|
||||||
RENAME_WINDOW: 'RENAME_WINDOW',
|
RENAME_WINDOW: 'RENAME_WINDOW',
|
||||||
TOOLBOX_WINDOW: 'TOOLBOX_WINDOW'
|
TOOLBOX_WINDOW: 'TOOLBOX_WINDOW'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IRemoteNoticeActionType = {
|
export const IRemoteNoticeActionType = {
|
||||||
OPEN_URL: 'OPEN_URL',
|
OPEN_URL: 'OPEN_URL',
|
||||||
SHOW_NOTICE: 'SHOW_NOTICE', // notification
|
SHOW_NOTICE: 'SHOW_NOTICE', // notification
|
||||||
SHOW_DIALOG: 'SHOW_DIALOG', // dialog notice
|
SHOW_DIALOG: 'SHOW_DIALOG', // dialog notice
|
||||||
COMMON: 'COMMON',
|
COMMON: 'COMMON',
|
||||||
VOID: 'VOID', // do nothing
|
VOID: 'VOID', // do nothing
|
||||||
SHOW_MESSAGE_BOX: 'SHOW_MESSAGE_BOX'
|
SHOW_MESSAGE_BOX: 'SHOW_MESSAGE_BOX'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IRemoteNoticeTriggerHook = {
|
export const IRemoteNoticeTriggerHook = {
|
||||||
APP_START: 'APP_START',
|
APP_START: 'APP_START',
|
||||||
SETTING_WINDOW_OPEN: 'SETTING_WINDOW_OPEN'
|
SETTING_WINDOW_OPEN: 'SETTING_WINDOW_OPEN'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IRemoteNoticeTriggerCount = {
|
export const IRemoteNoticeTriggerCount = {
|
||||||
ONCE: 'ONCE', // default
|
ONCE: 'ONCE', // default
|
||||||
ALWAYS: 'ALWAYS'
|
ALWAYS: 'ALWAYS'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IRPCType = {
|
export const IRPCType = {
|
||||||
INVOKE: 'INVOKE',
|
INVOKE: 'INVOKE',
|
||||||
SEND: 'SEND'
|
SEND: 'SEND'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IRPCActionType = {
|
export const IRPCActionType = {
|
||||||
// system rpc
|
// system rpc
|
||||||
RELOAD_APP: 'RELOAD_APP',
|
RELOAD_APP: 'RELOAD_APP',
|
||||||
OPEN_URL: 'OPEN_URL',
|
OPEN_URL: 'OPEN_URL',
|
||||||
OPEN_FILE: 'OPEN_FILE',
|
OPEN_FILE: 'OPEN_FILE',
|
||||||
HIDE_DOCK: 'HIDE_DOCK',
|
HIDE_DOCK: 'HIDE_DOCK',
|
||||||
SET_CURRENT_LANGUAGE: 'SET_CURRENT_LANGUAGE',
|
SET_CURRENT_LANGUAGE: 'SET_CURRENT_LANGUAGE',
|
||||||
OPEN_WINDOW: 'OPEN_WINDOW',
|
OPEN_WINDOW: 'OPEN_WINDOW',
|
||||||
OPEN_MINI_WINDOW: 'OPEN_MINI_WINDOW',
|
OPEN_MINI_WINDOW: 'OPEN_MINI_WINDOW',
|
||||||
CLOSE_WINDOW: 'CLOSE_WINDOW',
|
CLOSE_WINDOW: 'CLOSE_WINDOW',
|
||||||
MINIMIZE_WINDOW: 'MINIMIZE_WINDOW',
|
MINIMIZE_WINDOW: 'MINIMIZE_WINDOW',
|
||||||
SHOW_MINI_PAGE_MENU: 'SHOW_MINI_PAGE_MENU',
|
SHOW_MINI_PAGE_MENU: 'SHOW_MINI_PAGE_MENU',
|
||||||
SHOW_MAIN_PAGE_MENU: 'SHOW_MAIN_PAGE_MENU',
|
SHOW_MAIN_PAGE_MENU: 'SHOW_MAIN_PAGE_MENU',
|
||||||
SHOW_UPLOAD_PAGE_MENU: 'SHOW_UPLOAD_PAGE_MENU',
|
SHOW_UPLOAD_PAGE_MENU: 'SHOW_UPLOAD_PAGE_MENU',
|
||||||
SHOW_SECOND_UPLOADER_MENU: 'SHOW_SECOND_UPLOADER_MENU',
|
SHOW_SECOND_UPLOADER_MENU: 'SHOW_SECOND_UPLOADER_MENU',
|
||||||
SHOW_PLUGIN_PAGE_MENU: 'SHOW_PLUGIN_PAGE_MENU',
|
SHOW_PLUGIN_PAGE_MENU: 'SHOW_PLUGIN_PAGE_MENU',
|
||||||
SET_MINI_WINDOW_POS: 'SET_MINI_WINDOW_POS',
|
SET_MINI_WINDOW_POS: 'SET_MINI_WINDOW_POS',
|
||||||
MINI_WINDOW_ON_TOP: 'MINI_WINDOW_ON_TOP',
|
MINI_WINDOW_ON_TOP: 'MINI_WINDOW_ON_TOP',
|
||||||
MAIN_WINDOW_ON_TOP: 'MAIN_WINDOW_ON_TOP',
|
MAIN_WINDOW_ON_TOP: 'MAIN_WINDOW_ON_TOP',
|
||||||
UPDATE_MINI_WINDOW_ICON: 'UPDATE_MINI_WINDOW_ICON',
|
UPDATE_MINI_WINDOW_ICON: 'UPDATE_MINI_WINDOW_ICON',
|
||||||
REFRESH_SETTING_WINDOW: 'REFRESH_SETTING_WINDOW',
|
REFRESH_SETTING_WINDOW: 'REFRESH_SETTING_WINDOW',
|
||||||
// picbed RPC
|
// picbed RPC
|
||||||
PICBED_GET_PICBED_CONFIG: 'PICBED_GET_PICBED_CONFIG',
|
PICBED_GET_PICBED_CONFIG: 'PICBED_GET_PICBED_CONFIG',
|
||||||
PICBED_GET_CONFIG_LIST: 'PICBED_GET_CONFIG_LIST',
|
PICBED_GET_CONFIG_LIST: 'PICBED_GET_CONFIG_LIST',
|
||||||
PICBED_DELETE_CONFIG: 'PICBED_DELETE_CONFIG',
|
PICBED_DELETE_CONFIG: 'PICBED_DELETE_CONFIG',
|
||||||
UPLOADER_CHANGE_CURRENT: 'UPLOADER_CHANGE_CURRENT',
|
UPLOADER_CHANGE_CURRENT: 'UPLOADER_CHANGE_CURRENT',
|
||||||
UPLOADER_SELECT: 'UPLOADER_SELECT',
|
UPLOADER_SELECT: 'UPLOADER_SELECT',
|
||||||
UPLOADER_UPDATE_CONFIG: 'UPLOADER_UPDATE_CONFIG',
|
UPLOADER_UPDATE_CONFIG: 'UPLOADER_UPDATE_CONFIG',
|
||||||
UPLOADER_RESET_CONFIG: 'UPLOADER_RESET_CONFIG',
|
UPLOADER_RESET_CONFIG: 'UPLOADER_RESET_CONFIG',
|
||||||
DELETE_ALL_API: 'DELETE_ALL_API',
|
DELETE_ALL_API: 'DELETE_ALL_API',
|
||||||
|
|
||||||
// toolbox rpc
|
// toolbox rpc
|
||||||
TOOLBOX_CHECK: 'TOOLBOX_CHECK',
|
TOOLBOX_CHECK: 'TOOLBOX_CHECK',
|
||||||
TOOLBOX_CHECK_RES: 'TOOLBOX_CHECK_RES',
|
TOOLBOX_CHECK_RES: 'TOOLBOX_CHECK_RES',
|
||||||
TOOLBOX_CHECK_FIX: 'TOOLBOX_CHECK_FIX',
|
TOOLBOX_CHECK_FIX: 'TOOLBOX_CHECK_FIX',
|
||||||
|
|
||||||
// main app setting rpc
|
// main app setting rpc
|
||||||
PICLIST_GET_CONFIG: 'PICLIST_GET_CONFIG',
|
PICLIST_GET_CONFIG: 'PICLIST_GET_CONFIG',
|
||||||
PICLIST_GET_CONFIG_SYNC: 'PICLIST_GET_CONFIG_SYNC',
|
PICLIST_GET_CONFIG_SYNC: 'PICLIST_GET_CONFIG_SYNC',
|
||||||
PICLIST_SAVE_CONFIG: 'PICLIST_SAVE_CONFIG',
|
PICLIST_SAVE_CONFIG: 'PICLIST_SAVE_CONFIG',
|
||||||
PICLIST_OPEN_FILE: 'PICLIST_OPEN_FILE',
|
PICLIST_OPEN_FILE: 'PICLIST_OPEN_FILE',
|
||||||
PICLIST_OPEN_DIRECTORY: 'PICLIST_OPEN_DIRECTORY',
|
PICLIST_OPEN_DIRECTORY: 'PICLIST_OPEN_DIRECTORY',
|
||||||
PICLIST_AUTO_START: 'PICLIST_AUTO_START',
|
PICLIST_AUTO_START: 'PICLIST_AUTO_START',
|
||||||
|
|
||||||
// shortkey setting rpc
|
// shortkey setting rpc
|
||||||
SHORTKEY_UPDATE: 'SHORTKEY_UPDATE',
|
SHORTKEY_UPDATE: 'SHORTKEY_UPDATE',
|
||||||
SHORTKEY_BIND_OR_UNBIND: 'SHORTKEY_BIND_OR_UNBIND',
|
SHORTKEY_BIND_OR_UNBIND: 'SHORTKEY_BIND_OR_UNBIND',
|
||||||
SHORTKEY_TOGGLE_SHORTKEY_MODIFIED_MODE: 'SHORTKEY_TOGGLE_SHORTKEY_MODIFIED_MODE',
|
SHORTKEY_TOGGLE_SHORTKEY_MODIFIED_MODE: 'SHORTKEY_TOGGLE_SHORTKEY_MODIFIED_MODE',
|
||||||
|
|
||||||
// configuration setting rpc
|
// configuration setting rpc
|
||||||
CONFIGURE_MIGRATE_FROM_PICGO: 'CONFIGURE_MIGRATE_FROM_PICGO',
|
CONFIGURE_MIGRATE_FROM_PICGO: 'CONFIGURE_MIGRATE_FROM_PICGO',
|
||||||
CONFIGURE_UPLOAD_COMMON_CONFIG: 'CONFIGURE_UPLOAD_COMMON_CONFIG',
|
CONFIGURE_UPLOAD_COMMON_CONFIG: 'CONFIGURE_UPLOAD_COMMON_CONFIG',
|
||||||
CONFIGURE_UPLOAD_MANAGE_CONFIG: 'CONFIGURE_UPLOAD_MANAGE_CONFIG',
|
CONFIGURE_UPLOAD_MANAGE_CONFIG: 'CONFIGURE_UPLOAD_MANAGE_CONFIG',
|
||||||
CONFIGURE_UPLOAD_ALL_CONFIG: 'CONFIGURE_UPLOAD_ALL_CONFIG',
|
CONFIGURE_UPLOAD_ALL_CONFIG: 'CONFIGURE_UPLOAD_ALL_CONFIG',
|
||||||
CONFIGURE_DOWNLOAD_COMMON_CONFIG: 'CONFIGURE_DOWNLOAD_COMMON_CONFIG',
|
CONFIGURE_DOWNLOAD_COMMON_CONFIG: 'CONFIGURE_DOWNLOAD_COMMON_CONFIG',
|
||||||
CONFIGURE_DOWNLOAD_MANAGE_CONFIG: 'CONFIGURE_DOWNLOAD_MANAGE_CONFIG',
|
CONFIGURE_DOWNLOAD_MANAGE_CONFIG: 'CONFIGURE_DOWNLOAD_MANAGE_CONFIG',
|
||||||
CONFIGURE_DOWNLOAD_ALL_CONFIG: 'CONFIGURE_DOWNLOAD_ALL_CONFIG',
|
CONFIGURE_DOWNLOAD_ALL_CONFIG: 'CONFIGURE_DOWNLOAD_ALL_CONFIG',
|
||||||
|
|
||||||
// advanced setting rpc
|
// advanced setting rpc
|
||||||
ADVANCED_UPDATE_SERVER: 'ADVANCED_UPDATE_SERVER',
|
ADVANCED_UPDATE_SERVER: 'ADVANCED_UPDATE_SERVER',
|
||||||
ADVANCED_STOP_WEB_SERVER: 'ADVANCED_STOP_WEB_SERVER',
|
ADVANCED_STOP_WEB_SERVER: 'ADVANCED_STOP_WEB_SERVER',
|
||||||
ADVANCED_RESTART_WEB_SERVER: 'ADVANCED_RESTART_WEB_SERVER',
|
ADVANCED_RESTART_WEB_SERVER: 'ADVANCED_RESTART_WEB_SERVER',
|
||||||
|
|
||||||
// upload and main page rpc
|
// upload and main page rpc
|
||||||
MAIN_GET_PICBED: 'MAIN_GET_PICBED',
|
MAIN_GET_PICBED: 'MAIN_GET_PICBED',
|
||||||
UPLOAD_CLIPBOARD_FILES_FROM_UPLOAD_PAGE: 'UPLOAD_CLIPBOARD_FILES_FROM_UPLOAD_PAGE',
|
UPLOAD_CLIPBOARD_FILES_FROM_UPLOAD_PAGE: 'UPLOAD_CLIPBOARD_FILES_FROM_UPLOAD_PAGE',
|
||||||
UPLOAD_CHOOSED_FILES: 'UPLOAD_CHOOSED_FILES',
|
UPLOAD_CHOOSED_FILES: 'UPLOAD_CHOOSED_FILES',
|
||||||
|
|
||||||
// gallery rpc
|
// gallery rpc
|
||||||
GALLERY_PASTE_TEXT: 'GALLERY_PASTE_TEXT',
|
GALLERY_PASTE_TEXT: 'GALLERY_PASTE_TEXT',
|
||||||
GALLERY_REMOVE_FILES: 'GALLERY_REMOVE_FILES',
|
GALLERY_REMOVE_FILES: 'GALLERY_REMOVE_FILES',
|
||||||
GALLERY_GET_DB: 'GALLERY_GET_DB',
|
GALLERY_GET_DB: 'GALLERY_GET_DB',
|
||||||
GALLERY_GET_BY_ID_DB: 'GALLERY_GET_BY_ID_DB',
|
GALLERY_GET_BY_ID_DB: 'GALLERY_GET_BY_ID_DB',
|
||||||
GALLERY_UPDATE_BY_ID_DB: 'GALLERY_UPDATE_BY_ID_DB',
|
GALLERY_UPDATE_BY_ID_DB: 'GALLERY_UPDATE_BY_ID_DB',
|
||||||
GALLERY_REMOVE_BY_ID_DB: 'GALLERY_REMOVE_BY_ID_DB',
|
GALLERY_REMOVE_BY_ID_DB: 'GALLERY_REMOVE_BY_ID_DB',
|
||||||
GALLERY_INSERT_DB: 'GALLERY_INSERT_DB',
|
GALLERY_INSERT_DB: 'GALLERY_INSERT_DB',
|
||||||
GALLERY_INSERT_DB_BATCH: 'GALLERY_INSERT_DB_BATCH',
|
GALLERY_INSERT_DB_BATCH: 'GALLERY_INSERT_DB_BATCH',
|
||||||
// plugin rpc
|
// plugin rpc
|
||||||
PLUGIN_GET_LIST: 'PLUGIN_GET_LIST',
|
PLUGIN_GET_LIST: 'PLUGIN_GET_LIST',
|
||||||
PLUGIN_INSTALL: 'PLUGIN_INSTALL',
|
PLUGIN_INSTALL: 'PLUGIN_INSTALL',
|
||||||
PLUGIN_IMPORT_LOCAL: 'PLUGIN_IMPORT_LOCAL',
|
PLUGIN_IMPORT_LOCAL: 'PLUGIN_IMPORT_LOCAL',
|
||||||
PLUGIN_UPDATE_ALL: 'PLUGIN_UPDATE_ALL',
|
PLUGIN_UPDATE_ALL: 'PLUGIN_UPDATE_ALL',
|
||||||
|
|
||||||
// tray rpc
|
// tray rpc
|
||||||
TRAY_SET_TOOL_TIP: 'TRAY_SET_TOOL_TIP',
|
TRAY_SET_TOOL_TIP: 'TRAY_SET_TOOL_TIP',
|
||||||
TRAY_GET_SHORT_URL: 'TRAY_GET_SHORT_URL',
|
TRAY_GET_SHORT_URL: 'TRAY_GET_SHORT_URL',
|
||||||
TRAY_UPLOAD_CLIPBOARD_FILES: 'TRAY_UPLOAD_CLIPBOARD_FILES',
|
TRAY_UPLOAD_CLIPBOARD_FILES: 'TRAY_UPLOAD_CLIPBOARD_FILES',
|
||||||
|
|
||||||
// manage rpc
|
// manage rpc
|
||||||
MANAGE_GET_CONFIG: 'MANAGE_GET_CONFIG',
|
MANAGE_GET_CONFIG: 'MANAGE_GET_CONFIG',
|
||||||
MANAGE_SAVE_CONFIG: 'MANAGE_SAVE_CONFIG',
|
MANAGE_SAVE_CONFIG: 'MANAGE_SAVE_CONFIG',
|
||||||
MANAGE_REMOVE_CONFIG: 'MANAGE_REMOVE_CONFIG',
|
MANAGE_REMOVE_CONFIG: 'MANAGE_REMOVE_CONFIG',
|
||||||
MANAGE_GET_BUCKET_LIST: 'MANAGE_GET_BUCKET_LIST',
|
MANAGE_GET_BUCKET_LIST: 'MANAGE_GET_BUCKET_LIST',
|
||||||
MANAGE_GET_BUCKET_LIST_BACKSTAGE: 'MANAGE_GET_BUCKET_LIST_BACKSTAGE',
|
MANAGE_GET_BUCKET_LIST_BACKSTAGE: 'MANAGE_GET_BUCKET_LIST_BACKSTAGE',
|
||||||
MANAGE_GET_BUCKET_LIST_RECURSIVELY: 'MANAGE_GET_BUCKET_LIST_RECURSIVELY',
|
MANAGE_GET_BUCKET_LIST_RECURSIVELY: 'MANAGE_GET_BUCKET_LIST_RECURSIVELY',
|
||||||
MANAGE_CREATE_BUCKET: 'MANAGE_CREATE_BUCKET',
|
MANAGE_CREATE_BUCKET: 'MANAGE_CREATE_BUCKET',
|
||||||
MANAGE_GET_BUCKET_FILE_LIST: 'MANAGE_GET_BUCKET_FILE_LIST',
|
MANAGE_GET_BUCKET_FILE_LIST: 'MANAGE_GET_BUCKET_FILE_LIST',
|
||||||
MANAGE_GET_BUCKET_DOMAIN: 'MANAGE_GET_BUCKET_DOMAIN',
|
MANAGE_GET_BUCKET_DOMAIN: 'MANAGE_GET_BUCKET_DOMAIN',
|
||||||
MANAGE_SET_BUCKET_ACL_POLICY: 'MANAGE_SET_BUCKET_ACL_POLICY',
|
MANAGE_SET_BUCKET_ACL_POLICY: 'MANAGE_SET_BUCKET_ACL_POLICY',
|
||||||
MANAGE_RENAME_BUCKET_FILE: 'MANAGE_RENAME_BUCKET_FILE',
|
MANAGE_RENAME_BUCKET_FILE: 'MANAGE_RENAME_BUCKET_FILE',
|
||||||
MANAGE_DELETE_BUCKET_FILE: 'MANAGE_DELETE_BUCKET_FILE',
|
MANAGE_DELETE_BUCKET_FILE: 'MANAGE_DELETE_BUCKET_FILE',
|
||||||
MANAGE_DELETE_BUCKET_FOLDER: 'MANAGE_DELETE_BUCKET_FOLDER',
|
MANAGE_DELETE_BUCKET_FOLDER: 'MANAGE_DELETE_BUCKET_FOLDER',
|
||||||
MANAGE_GET_PRE_SIGNED_URL: 'MANAGE_GET_PRE_SIGNED_URL',
|
MANAGE_GET_PRE_SIGNED_URL: 'MANAGE_GET_PRE_SIGNED_URL',
|
||||||
MANAGE_UPLOAD_BUCKET_FILE: 'MANAGE_UPLOAD_BUCKET_FILE',
|
MANAGE_UPLOAD_BUCKET_FILE: 'MANAGE_UPLOAD_BUCKET_FILE',
|
||||||
MANAGE_DOWNLOAD_BUCKET_FILE: 'MANAGE_DOWNLOAD_BUCKET_FILE',
|
MANAGE_DOWNLOAD_BUCKET_FILE: 'MANAGE_DOWNLOAD_BUCKET_FILE',
|
||||||
MANAGE_CREATE_BUCKET_FOLDER: 'MANAGE_CREATE_BUCKET_FOLDER',
|
MANAGE_CREATE_BUCKET_FOLDER: 'MANAGE_CREATE_BUCKET_FOLDER',
|
||||||
MANAGE_OPEN_FILE_SELECT_DIALOG: 'MANAGE_OPEN_FILE_SELECT_DIALOG',
|
MANAGE_OPEN_FILE_SELECT_DIALOG: 'MANAGE_OPEN_FILE_SELECT_DIALOG',
|
||||||
MANAGE_GET_UPLOAD_TASK_LIST: 'MANAGE_GET_UPLOAD_TASK_LIST',
|
MANAGE_GET_UPLOAD_TASK_LIST: 'MANAGE_GET_UPLOAD_TASK_LIST',
|
||||||
MANAGE_GET_DOWNLOAD_TASK_LIST: 'MANAGE_GET_DOWNLOAD_TASK_LIST',
|
MANAGE_GET_DOWNLOAD_TASK_LIST: 'MANAGE_GET_DOWNLOAD_TASK_LIST',
|
||||||
MANAGE_DELETE_UPLOADED_TASK: 'MANAGE_DELETE_UPLOADED_TASK',
|
MANAGE_DELETE_UPLOADED_TASK: 'MANAGE_DELETE_UPLOADED_TASK',
|
||||||
MANAGE_DELETE_ALL_UPLOADED_TASK: 'MANAGE_DELETE_ALL_UPLOADED_TASK',
|
MANAGE_DELETE_ALL_UPLOADED_TASK: 'MANAGE_DELETE_ALL_UPLOADED_TASK',
|
||||||
MANAGE_DELETE_DOWNLOADED_TASK: 'MANAGE_DELETE_DOWNLOADED_TASK',
|
MANAGE_DELETE_DOWNLOADED_TASK: 'MANAGE_DELETE_DOWNLOADED_TASK',
|
||||||
MANAGE_DELETE_ALL_DOWNLOADED_TASK: 'MANAGE_DELETE_ALL_DOWNLOADED_TASK',
|
MANAGE_DELETE_ALL_DOWNLOADED_TASK: 'MANAGE_DELETE_ALL_DOWNLOADED_TASK',
|
||||||
MANAGE_SELECT_DOWNLOAD_FOLDER: 'MANAGE_SELECT_DOWNLOAD_FOLDER',
|
MANAGE_SELECT_DOWNLOAD_FOLDER: 'MANAGE_SELECT_DOWNLOAD_FOLDER',
|
||||||
MANAGE_GET_DEFAULT_DOWNLOAD_FOLDER: 'MANAGE_GET_DEFAULT_DOWNLOAD_FOLDER',
|
MANAGE_GET_DEFAULT_DOWNLOAD_FOLDER: 'MANAGE_GET_DEFAULT_DOWNLOAD_FOLDER',
|
||||||
MANAGE_OPEN_DOWNLOADED_FOLDER: 'MANAGE_OPEN_DOWNLOADED_FOLDER',
|
MANAGE_OPEN_DOWNLOADED_FOLDER: 'MANAGE_OPEN_DOWNLOADED_FOLDER',
|
||||||
MANAGE_OPEN_LOCAL_FILE: 'MANAGE_OPEN_LOCAL_FILE',
|
MANAGE_OPEN_LOCAL_FILE: 'MANAGE_OPEN_LOCAL_FILE',
|
||||||
MANAGE_DOWNLOAD_FILE_FROM_URL: 'MANAGE_DOWNLOAD_FILE_FROM_URL',
|
MANAGE_DOWNLOAD_FILE_FROM_URL: 'MANAGE_DOWNLOAD_FILE_FROM_URL',
|
||||||
MANAGE_CONVERT_PATH_TO_BASE64: 'MANAGE_CONVERT_PATH_TO_BASE64'
|
MANAGE_CONVERT_PATH_TO_BASE64: 'MANAGE_CONVERT_PATH_TO_BASE64'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IToolboxItemType = {
|
export const IToolboxItemType = {
|
||||||
IS_CONFIG_FILE_BROKEN: 'IS_CONFIG_FILE_BROKEN',
|
IS_CONFIG_FILE_BROKEN: 'IS_CONFIG_FILE_BROKEN',
|
||||||
IS_GALLERY_FILE_BROKEN: 'IS_GALLERY_FILE_BROKEN',
|
IS_GALLERY_FILE_BROKEN: 'IS_GALLERY_FILE_BROKEN',
|
||||||
HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD: 'HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD',
|
HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD: 'HAS_PROBLEM_WITH_CLIPBOARD_PIC_UPLOAD',
|
||||||
HAS_PROBLEM_WITH_PROXY: 'HAS_PROBLEM_WITH_PROXY'
|
HAS_PROBLEM_WITH_PROXY: 'HAS_PROBLEM_WITH_PROXY'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IToolboxItemCheckStatus = {
|
export const IToolboxItemCheckStatus = {
|
||||||
INIT: 'init',
|
INIT: 'init',
|
||||||
LOADING: 'loading',
|
LOADING: 'loading',
|
||||||
SUCCESS: 'success',
|
SUCCESS: 'success',
|
||||||
ERROR: 'error'
|
ERROR: 'error'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ISartMode = {
|
export const ISartMode = {
|
||||||
QUIET: 'quiet',
|
QUIET: 'quiet',
|
||||||
MINI: 'mini',
|
MINI: 'mini',
|
||||||
MAIN: 'main',
|
MAIN: 'main',
|
||||||
NO_TRAY: 'no-tray'
|
NO_TRAY: 'no-tray'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const II18nLanguage = {
|
export const II18nLanguage = {
|
||||||
ZH_CN: 'zh-CN',
|
ZH_CN: 'zh-CN',
|
||||||
ZH_TW: 'zh-TW',
|
ZH_TW: 'zh-TW',
|
||||||
EN: 'en'
|
EN: 'en'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IShortUrlServer = {
|
export const IShortUrlServer = {
|
||||||
C1N: 'c1n',
|
C1N: 'c1n',
|
||||||
YOURLS: 'yourls',
|
YOURLS: 'yourls',
|
||||||
CFWORKER: 'cf_worker',
|
CFWORKER: 'cf_worker',
|
||||||
SINK: 'sink'
|
SINK: 'sink'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const commonTaskStatus = {
|
export const commonTaskStatus = {
|
||||||
queuing: 'queuing',
|
queuing: 'queuing',
|
||||||
failed: 'failed',
|
failed: 'failed',
|
||||||
canceled: 'canceled',
|
canceled: 'canceled',
|
||||||
paused: 'paused'
|
paused: 'paused'
|
||||||
}
|
}
|
||||||
|
|
||||||
// manage task status
|
// manage task status
|
||||||
|
|
||||||
export const uploadTaskSpecialStatus = {
|
export const uploadTaskSpecialStatus = {
|
||||||
uploading: 'uploading',
|
uploading: 'uploading',
|
||||||
uploaded: 'uploaded'
|
uploaded: 'uploaded'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const downloadTaskSpecialStatus = {
|
export const downloadTaskSpecialStatus = {
|
||||||
downloading: 'downloading',
|
downloading: 'downloading',
|
||||||
downloaded: 'downloaded'
|
downloaded: 'downloaded'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const parseVersion = (plist: string) => {
|
|||||||
return matches[1].replace('10.16', '11')
|
return matches[1].replace('10.16', '11')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function macOSVersion (): string {
|
export function macOSVersion(): string {
|
||||||
if (!isMacOS) return ''
|
if (!isMacOS) return ''
|
||||||
|
|
||||||
if (!version) {
|
if (!version) {
|
||||||
@@ -43,7 +43,7 @@ if (process.env.NODE_ENV === 'test') {
|
|||||||
macOSVersion._parseVersion = parseVersion
|
macOSVersion._parseVersion = parseVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isMacOSVersion (semverRange: string) {
|
export function isMacOSVersion(semverRange: string) {
|
||||||
if (!isMacOS) {
|
if (!isMacOS) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ export function isMacOSVersion (semverRange: string) {
|
|||||||
return semver.satisfies(macOSVersion(), clean(semverRange))
|
return semver.satisfies(macOSVersion(), clean(semverRange))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isMacOSVersionGreaterThanOrEqualTo (version: string) {
|
export function isMacOSVersionGreaterThanOrEqualTo(version: string) {
|
||||||
if (!isMacOS) {
|
if (!isMacOS) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ export function isMacOSVersionGreaterThanOrEqualTo (version: string) {
|
|||||||
return semver.gte(macOSVersion(), clean(version))
|
return semver.gte(macOSVersion(), clean(version))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertMacOSVersion (semverRange: string) {
|
export function assertMacOSVersion(semverRange: string) {
|
||||||
semverRange = semverRange.replace('10.16', '11')
|
semverRange = semverRange.replace('10.16', '11')
|
||||||
|
|
||||||
if (!isMacOSVersion(semverRange)) {
|
if (!isMacOSVersion(semverRange)) {
|
||||||
@@ -71,7 +71,7 @@ export function assertMacOSVersion (semverRange: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertMacOSVersionGreaterThanOrEqualTo (version: string) {
|
export function assertMacOSVersionGreaterThanOrEqualTo(version: string) {
|
||||||
version = version.replace('10.16', '11')
|
version = version.replace('10.16', '11')
|
||||||
|
|
||||||
if (!isMacOSVersionGreaterThanOrEqualTo(version)) {
|
if (!isMacOSVersionGreaterThanOrEqualTo(version)) {
|
||||||
@@ -79,7 +79,7 @@ export function assertMacOSVersionGreaterThanOrEqualTo (version: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertMacOS () {
|
export function assertMacOS() {
|
||||||
if (!isMacOS) {
|
if (!isMacOS) {
|
||||||
throw new Error('Requires macOS')
|
throw new Error('Requires macOS')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
import picgo from '@core/picgo'
|
import picgo from '@core/picgo'
|
||||||
import { v4 as uuid } from 'uuid'
|
import { v4 as uuid } from 'uuid'
|
||||||
|
|
||||||
import type { IPicGoPluginConfig, IPicGoPluginOriginConfig, IStringKeyMap, IUploaderConfigItem, IUploaderConfigListItem } from '#/types/types'
|
import type {
|
||||||
|
IPicGoPluginConfig,
|
||||||
|
IPicGoPluginOriginConfig,
|
||||||
|
IStringKeyMap,
|
||||||
|
IUploaderConfigItem,
|
||||||
|
IUploaderConfigListItem
|
||||||
|
} from '#/types/types'
|
||||||
import { setTrayToolTip, trimValues } from '~/utils/common'
|
import { setTrayToolTip, trimValues } from '~/utils/common'
|
||||||
import { configPaths } from '~/utils/configPaths'
|
import { configPaths } from '~/utils/configPaths'
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import type { IAppNotification } from '#/types/types'
|
import type { IAppNotification } from '#/types/types'
|
||||||
|
|
||||||
export const notificationList: IAppNotification[] = []
|
export const notificationList: IAppNotification[] = []
|
||||||
|
|||||||
@@ -1,31 +1,33 @@
|
|||||||
export class MemoryMonitor {
|
export class MemoryMonitor {
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
private static interval: NodeJS.Timeout | null = null
|
private static interval: NodeJS.Timeout | null = null
|
||||||
|
|
||||||
static start (intervalMs: number = 30000) {
|
static start(intervalMs: number = 30000) {
|
||||||
if (this.interval) return
|
if (this.interval) return
|
||||||
|
|
||||||
this.interval = setInterval(() => {
|
this.interval = setInterval(() => {
|
||||||
const memUsage = process.memoryUsage()
|
const memUsage = process.memoryUsage()
|
||||||
const mbUsage = {
|
const mbUsage = {
|
||||||
rss: Math.round(memUsage.rss / 1024 / 1024),
|
rss: Math.round(memUsage.rss / 1024 / 1024),
|
||||||
heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024),
|
heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024),
|
||||||
heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024),
|
heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024),
|
||||||
external: Math.round(memUsage.external / 1024 / 1024)
|
external: Math.round(memUsage.external / 1024 / 1024)
|
||||||
}
|
}
|
||||||
console.log(`[Memory] RSS: ${mbUsage.rss}MB, Heap: ${mbUsage.heapUsed}/${mbUsage.heapTotal}MB, External: ${mbUsage.external}MB`)
|
console.log(
|
||||||
|
`[Memory] RSS: ${mbUsage.rss}MB, Heap: ${mbUsage.heapUsed}/${mbUsage.heapTotal}MB, External: ${mbUsage.external}MB`
|
||||||
if (mbUsage.heapUsed / mbUsage.heapTotal > 0.8 && global.gc) {
|
)
|
||||||
console.log('[Memory] Triggering garbage collection')
|
|
||||||
global.gc()
|
if (mbUsage.heapUsed / mbUsage.heapTotal > 0.8 && global.gc) {
|
||||||
}
|
console.log('[Memory] Triggering garbage collection')
|
||||||
}, intervalMs)
|
global.gc()
|
||||||
}
|
}
|
||||||
|
}, intervalMs)
|
||||||
static stop () {
|
}
|
||||||
if (this.interval) {
|
|
||||||
clearInterval(this.interval)
|
static stop() {
|
||||||
this.interval = null
|
if (this.interval) {
|
||||||
}
|
clearInterval(this.interval)
|
||||||
}
|
this.interval = null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,194 +1,194 @@
|
|||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
|
|
||||||
import logger from '@core/picgo/logger'
|
import logger from '@core/picgo/logger'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import { Config, NodeSSH, SSHExecCommandResponse } from 'node-ssh-no-cpu-features'
|
import { Config, NodeSSH, SSHExecCommandResponse } from 'node-ssh-no-cpu-features'
|
||||||
import { ISftpPlistConfig } from 'piclist/dist/types'
|
import { ISftpPlistConfig } from 'piclist/dist/types'
|
||||||
import { Client } from 'ssh2-no-cpu-features'
|
import { Client } from 'ssh2-no-cpu-features'
|
||||||
|
|
||||||
class SSHClient {
|
class SSHClient {
|
||||||
private static _instance: SSHClient
|
private static _instance: SSHClient
|
||||||
private static _client: NodeSSH
|
private static _client: NodeSSH
|
||||||
private _isConnected = false
|
private _isConnected = false
|
||||||
|
|
||||||
static get instance (): SSHClient {
|
static get instance(): SSHClient {
|
||||||
return this._instance || (this._instance = new this())
|
return this._instance || (this._instance = new this())
|
||||||
}
|
}
|
||||||
|
|
||||||
static get client (): NodeSSH {
|
static get client(): NodeSSH {
|
||||||
return this._client || (this._client = new NodeSSH())
|
return this._client || (this._client = new NodeSSH())
|
||||||
}
|
}
|
||||||
|
|
||||||
private changeWinStylePathToUnix (path: string): string {
|
private changeWinStylePathToUnix(path: string): string {
|
||||||
return path.replace(/\\/g, '/')
|
return path.replace(/\\/g, '/')
|
||||||
}
|
}
|
||||||
|
|
||||||
async connect (config: ISftpPlistConfig): Promise<boolean> {
|
async connect(config: ISftpPlistConfig): Promise<boolean> {
|
||||||
const { username, password, privateKey, passphrase } = config
|
const { username, password, privateKey, passphrase } = config
|
||||||
const loginInfo: Config = privateKey
|
const loginInfo: Config = privateKey
|
||||||
? {
|
? {
|
||||||
username,
|
username,
|
||||||
privateKeyPath: privateKey,
|
privateKeyPath: privateKey,
|
||||||
passphrase: passphrase || undefined
|
passphrase: passphrase || undefined
|
||||||
}
|
}
|
||||||
: { username, password }
|
: { username, password }
|
||||||
try {
|
try {
|
||||||
await SSHClient.client.connect({
|
await SSHClient.client.connect({
|
||||||
host: config.host,
|
host: config.host,
|
||||||
port: Number(config.port) || 22,
|
port: Number(config.port) || 22,
|
||||||
...loginInfo
|
...loginInfo
|
||||||
})
|
})
|
||||||
this._isConnected = true
|
this._isConnected = true
|
||||||
return true
|
return true
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
throw new Error(err)
|
throw new Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteFileSFTP (config: ISftpPlistConfig, remote: string): Promise<boolean> {
|
async deleteFileSFTP(config: ISftpPlistConfig, remote: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const client = new Client()
|
const client = new Client()
|
||||||
const { username, password, privateKey, passphrase } = config
|
const { username, password, privateKey, passphrase } = config
|
||||||
const loginInfo: Config = privateKey
|
const loginInfo: Config = privateKey
|
||||||
? {
|
? {
|
||||||
username,
|
username,
|
||||||
privateKey: fs.readFileSync(privateKey),
|
privateKey: fs.readFileSync(privateKey),
|
||||||
passphrase: passphrase || undefined
|
passphrase: passphrase || undefined
|
||||||
}
|
}
|
||||||
: { username, password }
|
: { username, password }
|
||||||
remote = this.changeWinStylePathToUnix(remote)
|
remote = this.changeWinStylePathToUnix(remote)
|
||||||
if (remote === '/' || remote.includes('*')) return false
|
if (remote === '/' || remote.includes('*')) return false
|
||||||
const promise = new Promise((resolve, reject) => {
|
const promise = new Promise((resolve, reject) => {
|
||||||
client
|
client
|
||||||
.on('ready', () => {
|
.on('ready', () => {
|
||||||
client.sftp(
|
client.sftp(
|
||||||
(
|
(
|
||||||
err: any,
|
err: any,
|
||||||
sftp: {
|
sftp: {
|
||||||
unlink: (arg0: string, arg1: (err: any) => void) => void
|
unlink: (arg0: string, arg1: (err: any) => void) => void
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
// eslint-disable-next-line prefer-promise-reject-errors
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
if (err) reject(false)
|
if (err) reject(false)
|
||||||
sftp.unlink(remote, (err: any) => {
|
sftp.unlink(remote, (err: any) => {
|
||||||
// eslint-disable-next-line prefer-promise-reject-errors
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
if (err) reject(false)
|
if (err) reject(false)
|
||||||
client.end()
|
client.end()
|
||||||
resolve(true)
|
resolve(true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.connect({
|
.connect({
|
||||||
host: config.host,
|
host: config.host,
|
||||||
port: Number(config.port) || 22,
|
port: Number(config.port) || 22,
|
||||||
...loginInfo
|
...loginInfo
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return (await promise) as boolean
|
return (await promise) as boolean
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async exec (script: string): Promise<boolean> {
|
private async exec(script: string): Promise<boolean> {
|
||||||
const execResult = await SSHClient.client.execCommand(script)
|
const execResult = await SSHClient.client.execCommand(script)
|
||||||
return execResult.code === 0
|
return execResult.code === 0
|
||||||
}
|
}
|
||||||
|
|
||||||
async execCommand (script: string): Promise<SSHExecCommandResponse> {
|
async execCommand(script: string): Promise<SSHExecCommandResponse> {
|
||||||
const execResult = await SSHClient.client.execCommand(script)
|
const execResult = await SSHClient.client.execCommand(script)
|
||||||
return execResult || { code: 1, stdout: '', stderr: '' }
|
return execResult || { code: 1, stdout: '', stderr: '' }
|
||||||
}
|
}
|
||||||
|
|
||||||
async getFile (local: string, remote: string): Promise<boolean> {
|
async getFile(local: string, remote: string): Promise<boolean> {
|
||||||
if (!this._isConnected) {
|
if (!this._isConnected) {
|
||||||
throw new Error('SSH 未连接')
|
throw new Error('SSH 未连接')
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
remote = this.changeWinStylePathToUnix(remote)
|
remote = this.changeWinStylePathToUnix(remote)
|
||||||
local = this.changeWinStylePathToUnix(local)
|
local = this.changeWinStylePathToUnix(local)
|
||||||
await SSHClient.client.getFile(local, remote, undefined, {
|
await SSHClient.client.getFile(local, remote, undefined, {
|
||||||
concurrency: 1
|
concurrency: 1
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async putFile (
|
async putFile(
|
||||||
local: string,
|
local: string,
|
||||||
remote: string,
|
remote: string,
|
||||||
config: {
|
config: {
|
||||||
fileMode?: string
|
fileMode?: string
|
||||||
dirMode?: string
|
dirMode?: string
|
||||||
} = {}
|
} = {}
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
if (!this._isConnected) {
|
if (!this._isConnected) {
|
||||||
throw new Error('SSH 未连接')
|
throw new Error('SSH 未连接')
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
remote = this.changeWinStylePathToUnix(remote)
|
remote = this.changeWinStylePathToUnix(remote)
|
||||||
await this.mkdir(path.dirname(remote).replace(/^\/+|\/+$/g, ''), config)
|
await this.mkdir(path.dirname(remote).replace(/^\/+|\/+$/g, ''), config)
|
||||||
await SSHClient.client.putFile(local, remote)
|
await SSHClient.client.putFile(local, remote)
|
||||||
const fileMode = config.fileMode || '0644'
|
const fileMode = config.fileMode || '0644'
|
||||||
if (fileMode !== '0644') {
|
if (fileMode !== '0644') {
|
||||||
const script = `chmod ${fileMode} "${remote}"`
|
const script = `chmod ${fileMode} "${remote}"`
|
||||||
return await this.exec(script)
|
return await this.exec(script)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async mkdir (
|
async mkdir(
|
||||||
dirPath: string,
|
dirPath: string,
|
||||||
config: {
|
config: {
|
||||||
dirMode?: string
|
dirMode?: string
|
||||||
} = {}
|
} = {}
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
if (!this._isConnected) {
|
if (!this._isConnected) {
|
||||||
throw new Error('SSH 未连接')
|
throw new Error('SSH 未连接')
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const directoryMode = config.dirMode || '0755'
|
const directoryMode = config.dirMode || '0755'
|
||||||
if (directoryMode === '0755') {
|
if (directoryMode === '0755') {
|
||||||
const script = `mkdir -p "${dirPath}"`
|
const script = `mkdir -p "${dirPath}"`
|
||||||
return await this.exec(script)
|
return await this.exec(script)
|
||||||
} else {
|
} else {
|
||||||
const dirs = dirPath.split('/')
|
const dirs = dirPath.split('/')
|
||||||
let currentPath = ''
|
let currentPath = ''
|
||||||
for (const dir of dirs) {
|
for (const dir of dirs) {
|
||||||
if (dir) {
|
if (dir) {
|
||||||
currentPath += `/${dir}`
|
currentPath += `/${dir}`
|
||||||
const script = `mkdir "${currentPath}" && chmod ${directoryMode} "${currentPath}"`
|
const script = `mkdir "${currentPath}" && chmod ${directoryMode} "${currentPath}"`
|
||||||
const result = await this.exec(script)
|
const result = await this.exec(script)
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get isConnected (): boolean {
|
get isConnected(): boolean {
|
||||||
return SSHClient.client.isConnected()
|
return SSHClient.client.isConnected()
|
||||||
}
|
}
|
||||||
|
|
||||||
close (): void {
|
close(): void {
|
||||||
SSHClient.client.dispose()
|
SSHClient.client.dispose()
|
||||||
this._isConnected = false
|
this._isConnected = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SSHClient
|
export default SSHClient
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
export const CLIPBOARD_IMAGE_FOLDER = 'piclist-clipboard-images'
|
export const CLIPBOARD_IMAGE_FOLDER = 'piclist-clipboard-images'
|
||||||
|
|
||||||
export const cancelDownloadLoadingFileList = 'cancelDownloadLoadingFileList'
|
export const cancelDownloadLoadingFileList = 'cancelDownloadLoadingFileList'
|
||||||
export const refreshDownloadFileTransferList = 'refreshDownloadFileTransferList'
|
export const refreshDownloadFileTransferList = 'refreshDownloadFileTransferList'
|
||||||
|
|
||||||
export const picBedsCanbeDeleted = [
|
export const picBedsCanbeDeleted = [
|
||||||
'aliyun',
|
'aliyun',
|
||||||
'alist',
|
'alist',
|
||||||
'alistplist',
|
'alistplist',
|
||||||
'aws-s3',
|
'aws-s3',
|
||||||
'aws-s3-plist',
|
'aws-s3-plist',
|
||||||
'dogecloud',
|
'dogecloud',
|
||||||
'github',
|
'github',
|
||||||
'huaweicloud-uploader',
|
'huaweicloud-uploader',
|
||||||
'imgur',
|
'imgur',
|
||||||
'local',
|
'local',
|
||||||
'lskyplist',
|
'lskyplist',
|
||||||
'piclist',
|
'piclist',
|
||||||
'qiniu',
|
'qiniu',
|
||||||
'sftpplist',
|
'sftpplist',
|
||||||
'smms',
|
'smms',
|
||||||
'tcyun',
|
'tcyun',
|
||||||
'upyun',
|
'upyun',
|
||||||
'webdavplist'
|
'webdavplist'
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -37,16 +37,16 @@ const getSyncConfig = () => {
|
|||||||
const getProxyagent = (proxy: string | undefined) => {
|
const getProxyagent = (proxy: string | undefined) => {
|
||||||
return proxy
|
return proxy
|
||||||
? new HttpsProxyAgent({
|
? new HttpsProxyAgent({
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
keepAliveMsecs: 1000,
|
keepAliveMsecs: 1000,
|
||||||
rejectUnauthorized: false,
|
rejectUnauthorized: false,
|
||||||
proxy: proxy.replace('127.0.0.1', 'localhost'),
|
proxy: proxy.replace('127.0.0.1', 'localhost'),
|
||||||
scheduling: 'lifo'
|
scheduling: 'lifo'
|
||||||
})
|
})
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOctokit (syncConfig: ISyncConfig) {
|
function getOctokit(syncConfig: ISyncConfig) {
|
||||||
const { token, proxy } = syncConfig
|
const { token, proxy } = syncConfig
|
||||||
return new Octokit({
|
return new Octokit({
|
||||||
auth: token,
|
auth: token,
|
||||||
@@ -83,7 +83,7 @@ const isSyncConfigValidate = ({
|
|||||||
return type && username && repo && branch && token
|
return type && username && repo && branch && token
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadLocalToRemote (syncConfig: ISyncConfig, fileName: string) {
|
async function uploadLocalToRemote(syncConfig: ISyncConfig, fileName: string) {
|
||||||
const localFilePath = path.join(STORE_PATH, fileName)
|
const localFilePath = path.join(STORE_PATH, fileName)
|
||||||
if (!fs.existsSync(localFilePath)) {
|
if (!fs.existsSync(localFilePath)) {
|
||||||
return false
|
return false
|
||||||
@@ -161,7 +161,7 @@ async function uploadLocalToRemote (syncConfig: ISyncConfig, fileName: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateLocalToRemote (syncConfig: ISyncConfig, fileName: string) {
|
async function updateLocalToRemote(syncConfig: ISyncConfig, fileName: string) {
|
||||||
const localFilePath = path.join(STORE_PATH, fileName)
|
const localFilePath = path.join(STORE_PATH, fileName)
|
||||||
if (!fs.existsSync(localFilePath)) {
|
if (!fs.existsSync(localFilePath)) {
|
||||||
return false
|
return false
|
||||||
@@ -277,7 +277,7 @@ async function updateLocalToRemote (syncConfig: ISyncConfig, fileName: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadFile (fileName: string[]): Promise<number> {
|
async function uploadFile(fileName: string[]): Promise<number> {
|
||||||
const syncConfig = getSyncConfig()
|
const syncConfig = getSyncConfig()
|
||||||
if (!isSyncConfigValidate(syncConfig)) {
|
if (!isSyncConfigValidate(syncConfig)) {
|
||||||
logger.error('sync config is invalid')
|
logger.error('sync config is invalid')
|
||||||
@@ -302,7 +302,7 @@ async function uploadFile (fileName: string[]): Promise<number> {
|
|||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadAndWriteFile (url: string, localFilePath: string, config: any, isWriteJson = false) {
|
async function downloadAndWriteFile(url: string, localFilePath: string, config: any, isWriteJson = false) {
|
||||||
const res = await axios.get(url, config)
|
const res = await axios.get(url, config)
|
||||||
if (isHttpResSuccess(res)) {
|
if (isHttpResSuccess(res)) {
|
||||||
await fs.writeFile(
|
await fs.writeFile(
|
||||||
@@ -314,7 +314,7 @@ async function downloadAndWriteFile (url: string, localFilePath: string, config:
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadRemoteToLocal (syncConfig: ISyncConfig, fileName: string) {
|
async function downloadRemoteToLocal(syncConfig: ISyncConfig, fileName: string) {
|
||||||
const localFilePath = path.join(STORE_PATH, fileName)
|
const localFilePath = path.join(STORE_PATH, fileName)
|
||||||
const { username, repo, branch, token, proxy, type } = syncConfig
|
const { username, repo, branch, token, proxy, type } = syncConfig
|
||||||
try {
|
try {
|
||||||
@@ -394,7 +394,7 @@ async function downloadRemoteToLocal (syncConfig: ISyncConfig, fileName: string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadFile (fileName: string[]): Promise<number> {
|
async function downloadFile(fileName: string[]): Promise<number> {
|
||||||
const syncConfig = getSyncConfig()
|
const syncConfig = getSyncConfig()
|
||||||
if (!isSyncConfigValidate(syncConfig)) {
|
if (!isSyncConfigValidate(syncConfig)) {
|
||||||
logger.error('sync config is invalid')
|
logger.error('sync config is invalid')
|
||||||
|
|||||||
@@ -1,66 +1,72 @@
|
|||||||
import db from '@core/datastore'
|
import db from '@core/datastore'
|
||||||
import windowManager from 'apis/app/window/windowManager'
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
import { screen } from 'electron'
|
import { screen } from 'electron'
|
||||||
|
|
||||||
import { configPaths } from '~/utils/configPaths'
|
import { configPaths } from '~/utils/configPaths'
|
||||||
import { IWindowList } from '~/utils/enum'
|
import { IWindowList } from '~/utils/enum'
|
||||||
|
|
||||||
export function openMiniWindow (hideSettingWindow: boolean = true) {
|
export function openMiniWindow(hideSettingWindow: boolean = true) {
|
||||||
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)!
|
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)!
|
||||||
|
|
||||||
miniWindow.removeAllListeners('close')
|
miniWindow.removeAllListeners('close')
|
||||||
miniWindow.removeAllListeners('move')
|
miniWindow.removeAllListeners('move')
|
||||||
|
|
||||||
if (db.get(configPaths.settings.miniWindowOntop)) {
|
if (db.get(configPaths.settings.miniWindowOntop)) {
|
||||||
miniWindow.setAlwaysOnTop(true)
|
miniWindow.setAlwaysOnTop(true)
|
||||||
}
|
}
|
||||||
const { width, height } = screen.getPrimaryDisplay().workAreaSize
|
const { width, height } = screen.getPrimaryDisplay().workAreaSize
|
||||||
const lastPosition = db.get(configPaths.settings.miniWindowPosition)
|
const lastPosition = db.get(configPaths.settings.miniWindowPosition)
|
||||||
const setPositionFunc = () => {
|
const setPositionFunc = () => {
|
||||||
const position = miniWindow.getPosition()
|
const position = miniWindow.getPosition()
|
||||||
db.set(configPaths.settings.miniWindowPosition, position)
|
db.set(configPaths.settings.miniWindowPosition, position)
|
||||||
}
|
}
|
||||||
if (lastPosition) {
|
if (lastPosition) {
|
||||||
if (lastPosition[0] < 0 || lastPosition[0] > width || lastPosition[1] < 0 || lastPosition[1] > height) {
|
if (lastPosition[0] < 0 || lastPosition[0] > width || lastPosition[1] < 0 || lastPosition[1] > height) {
|
||||||
miniWindow.setPosition(width - 100, height - 100)
|
miniWindow.setPosition(width - 100, height - 100)
|
||||||
db.set(configPaths.settings.miniWindowPosition, [width - 100, height - 100])
|
db.set(configPaths.settings.miniWindowPosition, [width - 100, height - 100])
|
||||||
} else if (lastPosition[0] + miniWindow.getSize()[0] > width || lastPosition[1] + miniWindow.getSize()[1] > height) {
|
} else if (
|
||||||
miniWindow.setPosition(width - miniWindow.getSize()[0], height - miniWindow.getSize()[1])
|
lastPosition[0] + miniWindow.getSize()[0] > width ||
|
||||||
db.set(configPaths.settings.miniWindowPosition, [width - miniWindow.getSize()[0], height - miniWindow.getSize()[1]])
|
lastPosition[1] + miniWindow.getSize()[1] > height
|
||||||
} else {
|
) {
|
||||||
miniWindow.setPosition(lastPosition[0], lastPosition[1])
|
miniWindow.setPosition(width - miniWindow.getSize()[0], height - miniWindow.getSize()[1])
|
||||||
}
|
db.set(configPaths.settings.miniWindowPosition, [
|
||||||
} else {
|
width - miniWindow.getSize()[0],
|
||||||
miniWindow.setPosition(width - 100, height - 100)
|
height - miniWindow.getSize()[1]
|
||||||
}
|
])
|
||||||
|
} else {
|
||||||
miniWindow.on('close', setPositionFunc)
|
miniWindow.setPosition(lastPosition[0], lastPosition[1])
|
||||||
miniWindow.on('move', setPositionFunc)
|
}
|
||||||
miniWindow.show()
|
} else {
|
||||||
miniWindow.focus()
|
miniWindow.setPosition(width - 100, height - 100)
|
||||||
if (hideSettingWindow) {
|
}
|
||||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
|
||||||
settingWindow.hide()
|
miniWindow.on('close', setPositionFunc)
|
||||||
} else {
|
miniWindow.on('move', setPositionFunc)
|
||||||
const autoCloseMainWindow = db.get(configPaths.settings.autoCloseMainWindow) || false
|
miniWindow.show()
|
||||||
if (windowManager.has(IWindowList.SETTING_WINDOW) && autoCloseMainWindow) {
|
miniWindow.focus()
|
||||||
windowManager.get(IWindowList.SETTING_WINDOW)!.hide()
|
if (hideSettingWindow) {
|
||||||
}
|
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
}
|
settingWindow.hide()
|
||||||
}
|
} else {
|
||||||
|
const autoCloseMainWindow = db.get(configPaths.settings.autoCloseMainWindow) || false
|
||||||
export const openMainWindow = () => {
|
if (windowManager.has(IWindowList.SETTING_WINDOW) && autoCloseMainWindow) {
|
||||||
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
|
windowManager.get(IWindowList.SETTING_WINDOW)!.hide()
|
||||||
const autoCloseMiniWindow = db.get(configPaths.settings.autoCloseMiniWindow) || false
|
}
|
||||||
settingWindow!.show()
|
}
|
||||||
settingWindow!.focus()
|
}
|
||||||
if (windowManager.has(IWindowList.MINI_WINDOW) && autoCloseMiniWindow) {
|
|
||||||
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
|
export const openMainWindow = () => {
|
||||||
}
|
const settingWindow = windowManager.get(IWindowList.SETTING_WINDOW)
|
||||||
}
|
const autoCloseMiniWindow = db.get(configPaths.settings.autoCloseMiniWindow) || false
|
||||||
|
settingWindow!.show()
|
||||||
export const hideMiniWindow = () => {
|
settingWindow!.focus()
|
||||||
if (windowManager.has(IWindowList.MINI_WINDOW)) {
|
if (windowManager.has(IWindowList.MINI_WINDOW) && autoCloseMiniWindow) {
|
||||||
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
|
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const hideMiniWindow = () => {
|
||||||
|
if (windowManager.has(IWindowList.MINI_WINDOW)) {
|
||||||
|
windowManager.get(IWindowList.MINI_WINDOW)!.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,101 +1,101 @@
|
|||||||
import crypto from 'node:crypto'
|
import crypto from 'node:crypto'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
|
|
||||||
import { clipboard, contextBridge, ipcRenderer, IpcRendererEvent, webFrame, webUtils } from 'electron'
|
import { clipboard, contextBridge, ipcRenderer, IpcRendererEvent, webFrame, webUtils } from 'electron'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import yaml from 'js-yaml'
|
import yaml from 'js-yaml'
|
||||||
import mime from 'mime-types'
|
import mime from 'mime-types'
|
||||||
import { isReactive, isRef, toRaw, unref } from 'vue'
|
import { isReactive, isRef, toRaw, unref } from 'vue'
|
||||||
|
|
||||||
export const getRawData = (args: any): any => {
|
export const getRawData = (args: any): any => {
|
||||||
if (isRef(args)) return unref(args)
|
if (isRef(args)) return unref(args)
|
||||||
if (isReactive(args)) return toRaw(args)
|
if (isReactive(args)) return toRaw(args)
|
||||||
if (Array.isArray(args)) return args.map(getRawData)
|
if (Array.isArray(args)) return args.map(getRawData)
|
||||||
if (typeof args === 'object' && args !== null) {
|
if (typeof args === 'object' && args !== null) {
|
||||||
const data = {} as Record<string, any>
|
const data = {} as Record<string, any>
|
||||||
for (const key in args) {
|
for (const key in args) {
|
||||||
data[key] = getRawData(args[key])
|
data[key] = getRawData(args[key])
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendToMain (channel: string, ...args: any[]) {
|
function sendToMain(channel: string, ...args: any[]) {
|
||||||
ipcRenderer.send(channel, ...getRawData(args))
|
ipcRenderer.send(channel, ...getRawData(args))
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendRPC (action: string, ...args: any[]): void {
|
function sendRPC(action: string, ...args: any[]): void {
|
||||||
ipcRenderer.send('RPC_ACTIONS', action, getRawData(args))
|
ipcRenderer.send('RPC_ACTIONS', action, getRawData(args))
|
||||||
}
|
}
|
||||||
|
|
||||||
async function triggerRPC<T> (action: string, ...args: any[]): Promise<T | undefined> {
|
async function triggerRPC<T>(action: string, ...args: any[]): Promise<T | undefined> {
|
||||||
return await ipcRenderer.invoke('RPC_ACTIONS_INVOKE', action, getRawData(args))
|
return await ipcRenderer.invoke('RPC_ACTIONS_INVOKE', action, getRawData(args))
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendRpcSync (action: string, ...args: any[]): any {
|
function sendRpcSync(action: string, ...args: any[]): any {
|
||||||
return ipcRenderer.sendSync('RPC_ACTIONS', action, getRawData(args))
|
return ipcRenderer.sendSync('RPC_ACTIONS', action, getRawData(args))
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
contextBridge.exposeInMainWorld('electron', {
|
contextBridge.exposeInMainWorld('electron', {
|
||||||
setVisualZoomLevelLimits: (min: number, max: number) => {
|
setVisualZoomLevelLimits: (min: number, max: number) => {
|
||||||
webFrame.setVisualZoomLevelLimits(min, max)
|
webFrame.setVisualZoomLevelLimits(min, max)
|
||||||
},
|
},
|
||||||
clipboard: {
|
clipboard: {
|
||||||
writeText: clipboard.writeText
|
writeText: clipboard.writeText
|
||||||
},
|
},
|
||||||
platform: process.platform,
|
platform: process.platform,
|
||||||
sendRpcSync,
|
sendRpcSync,
|
||||||
triggerRPC,
|
triggerRPC,
|
||||||
sendToMain,
|
sendToMain,
|
||||||
sendRPC,
|
sendRPC,
|
||||||
ipcRendererOn: (channel: string, listener: (...args: any[]) => void) => {
|
ipcRendererOn: (channel: string, listener: (...args: any[]) => void) => {
|
||||||
const subscription = (_: IpcRendererEvent, ...args: any[]) => listener(...args)
|
const subscription = (_: IpcRendererEvent, ...args: any[]) => listener(...args)
|
||||||
ipcRenderer.on(channel, subscription)
|
ipcRenderer.on(channel, subscription)
|
||||||
return () => {
|
return () => {
|
||||||
ipcRenderer.removeListener(channel, subscription)
|
ipcRenderer.removeListener(channel, subscription)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ipcRendererCountListeners: (channel: string): number => {
|
ipcRendererCountListeners: (channel: string): number => {
|
||||||
return ipcRenderer.listenerCount(channel)
|
return ipcRenderer.listenerCount(channel)
|
||||||
},
|
},
|
||||||
ipcRendererRemoveAllListeners: (channel: string) => {
|
ipcRendererRemoveAllListeners: (channel: string) => {
|
||||||
ipcRenderer.removeAllListeners(channel)
|
ipcRenderer.removeAllListeners(channel)
|
||||||
},
|
},
|
||||||
showFilePath (file: File) {
|
showFilePath(file: File) {
|
||||||
return webUtils.getPathForFile(file)
|
return webUtils.getPathForFile(file)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('node', {
|
contextBridge.exposeInMainWorld('node', {
|
||||||
path: {
|
path: {
|
||||||
join: path.join,
|
join: path.join,
|
||||||
dirname: path.dirname,
|
dirname: path.dirname,
|
||||||
basename: path.basename,
|
basename: path.basename,
|
||||||
normalize: path.normalize,
|
normalize: path.normalize,
|
||||||
extname: path.extname,
|
extname: path.extname,
|
||||||
sep: path.sep,
|
sep: path.sep,
|
||||||
posix: {
|
posix: {
|
||||||
sep: path.posix.sep
|
sep: path.posix.sep
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fs: {
|
fs: {
|
||||||
remove: fs.remove,
|
remove: fs.remove,
|
||||||
readFile: fs.readFile,
|
readFile: fs.readFile,
|
||||||
statSync: fs.statSync
|
statSync: fs.statSync
|
||||||
},
|
},
|
||||||
crypto: {
|
crypto: {
|
||||||
randomBytes: crypto.randomBytes,
|
randomBytes: crypto.randomBytes,
|
||||||
createHash: crypto.createHash
|
createHash: crypto.createHash
|
||||||
},
|
},
|
||||||
yaml: {
|
yaml: {
|
||||||
load: yaml.load
|
load: yaml.load
|
||||||
},
|
},
|
||||||
mime: {
|
mime: {
|
||||||
lookup: mime.lookup
|
lookup: mime.lookup
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,60 +1,56 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div id="app" :key="pageReloadCount">
|
||||||
id="app"
|
<router-view />
|
||||||
:key="pageReloadCount"
|
<UIServiceProvider />
|
||||||
>
|
</div>
|
||||||
<router-view />
|
</template>
|
||||||
<UIServiceProvider />
|
|
||||||
</div>
|
<script lang="ts" setup>
|
||||||
</template>
|
import type { IConfig } from 'piclist'
|
||||||
|
import { onBeforeMount, onMounted } from 'vue'
|
||||||
<script lang="ts" setup>
|
|
||||||
import type { IConfig } from 'piclist'
|
import UIServiceProvider from '@/components/ui/UIServiceProvider.vue'
|
||||||
import { onBeforeMount, onMounted } from 'vue'
|
import { useATagClick } from '@/hooks/useATagClick'
|
||||||
|
import { useStore } from '@/hooks/useStore'
|
||||||
import UIServiceProvider from '@/components/ui/UIServiceProvider.vue'
|
import { getConfig } from '@/utils/dataSender'
|
||||||
import { useATagClick } from '@/hooks/useATagClick'
|
import { pageReloadCount } from '@/utils/global'
|
||||||
import { useStore } from '@/hooks/useStore'
|
|
||||||
import { getConfig } from '@/utils/dataSender'
|
import { useAppStore } from './hooks/useAppStore'
|
||||||
import { pageReloadCount } from '@/utils/global'
|
|
||||||
|
useATagClick()
|
||||||
import { useAppStore } from './hooks/useAppStore'
|
|
||||||
|
const store = useStore()
|
||||||
useATagClick()
|
const appStore = useAppStore()
|
||||||
|
|
||||||
const store = useStore()
|
onBeforeMount(async () => {
|
||||||
const appStore = useAppStore()
|
const config = await getConfig<IConfig>()
|
||||||
|
if (config) {
|
||||||
onBeforeMount(async () => {
|
store?.setDefaultPicBed(config?.picBed?.uploader || config?.picBed?.current || 'smms')
|
||||||
const config = await getConfig<IConfig>()
|
}
|
||||||
if (config) {
|
})
|
||||||
store?.setDefaultPicBed(config?.picBed?.uploader || config?.picBed?.current || 'smms')
|
|
||||||
}
|
onMounted(async () => {
|
||||||
})
|
try {
|
||||||
|
appStore.init()
|
||||||
onMounted(async () => {
|
} catch (error) {
|
||||||
try {
|
console.error('Failed to load settings:', error)
|
||||||
appStore.init()
|
}
|
||||||
} catch (error) {
|
})
|
||||||
console.error('Failed to load settings:', error)
|
</script>
|
||||||
}
|
|
||||||
})
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
</script>
|
name: 'PicGoApp'
|
||||||
|
}
|
||||||
<script lang="ts">
|
</script>
|
||||||
export default {
|
|
||||||
name: 'PicGoApp'
|
<style lang="stylus">
|
||||||
}
|
body,
|
||||||
</script>
|
html
|
||||||
|
padding 0
|
||||||
<style lang="stylus">
|
margin 0
|
||||||
body,
|
height 100%
|
||||||
html
|
#app
|
||||||
padding 0
|
height 100%
|
||||||
margin 0
|
user-select none
|
||||||
height 100%
|
</style>
|
||||||
#app
|
|
||||||
height 100%
|
|
||||||
user-select none
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { IRPCActionType } from '@/utils/enum'
|
|||||||
import type { IStringKeyMap } from '#/types/types'
|
import type { IStringKeyMap } from '#/types/types'
|
||||||
|
|
||||||
export default class ALLApi {
|
export default class ALLApi {
|
||||||
static async delete (configMap: IStringKeyMap): Promise<boolean> {
|
static async delete(configMap: IStringKeyMap): Promise<boolean> {
|
||||||
return (await window.electron.triggerRPC(IRPCActionType.DELETE_ALL_API, getRawData(configMap))) || false
|
return (await window.electron.triggerRPC(IRPCActionType.DELETE_ALL_API, getRawData(configMap))) || false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,115 +1,107 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="image-container">
|
<div class="image-container">
|
||||||
<div
|
<div v-if="isLoading" class="loading-placeholder">
|
||||||
v-if="isLoading"
|
<div class="loading-spinner" />
|
||||||
class="loading-placeholder"
|
</div>
|
||||||
>
|
<img
|
||||||
<div class="loading-spinner" />
|
v-else-if="!hasError"
|
||||||
</div>
|
:src="isShowThumbnail && item.isImage ? base64Image : `./assets/icons/${getFileIconPath(item.fileName ?? '')}`"
|
||||||
<img
|
alt=""
|
||||||
v-else-if="!hasError"
|
class="image"
|
||||||
:src="
|
@load="handleImageLoad"
|
||||||
isShowThumbnail && item.isImage
|
@error="handleImageError"
|
||||||
? base64Image
|
/>
|
||||||
: `./assets/icons/${getFileIconPath(item.fileName ?? '')}`
|
<img v-else :src="`./assets/icons/${getFileIconPath(item.fileName ?? '')}`" alt="" class="image" />
|
||||||
"
|
</div>
|
||||||
alt=""
|
</template>
|
||||||
class="image"
|
|
||||||
@load="handleImageLoad"
|
<script lang="ts" setup>
|
||||||
@error="handleImageError"
|
import { onBeforeMount, ref } from 'vue'
|
||||||
>
|
|
||||||
<img
|
import { getFileIconPath } from '@/manage/utils/common'
|
||||||
v-else
|
|
||||||
:src="`./assets/icons/${getFileIconPath(item.fileName ?? '')}`"
|
const base64Image = ref('')
|
||||||
alt=""
|
const isLoading = ref(true)
|
||||||
class="image"
|
const hasError = ref(false)
|
||||||
>
|
|
||||||
</div>
|
const props = defineProps<{
|
||||||
</template>
|
isShowThumbnail: boolean
|
||||||
|
item: {
|
||||||
<script lang="ts" setup>
|
isImage: boolean
|
||||||
import { onBeforeMount, ref } from 'vue'
|
fileName: string
|
||||||
|
}
|
||||||
import { getFileIconPath } from '@/manage/utils/common'
|
localPath: string
|
||||||
|
}>()
|
||||||
const base64Image = ref('')
|
|
||||||
const isLoading = ref(true)
|
const createBase64Image = async () => {
|
||||||
const hasError = ref(false)
|
try {
|
||||||
|
const filePath = window.node.path.normalize(props.localPath)
|
||||||
const props = defineProps<{
|
const base64 = await window.node.fs.readFile(filePath, 'base64')
|
||||||
isShowThumbnail: boolean
|
base64Image.value = `data:${window.node.mime.lookup(filePath) || 'image/png'};base64,${base64}`
|
||||||
item: {
|
isLoading.value = false
|
||||||
isImage: boolean
|
} catch (e) {
|
||||||
fileName: string
|
console.log(e)
|
||||||
}
|
hasError.value = true
|
||||||
localPath: string
|
isLoading.value = false
|
||||||
}>()
|
}
|
||||||
|
}
|
||||||
const createBase64Image = async () => {
|
|
||||||
try {
|
const handleImageLoad = () => {
|
||||||
const filePath = window.node.path.normalize(props.localPath)
|
isLoading.value = false
|
||||||
const base64 = await window.node.fs.readFile(filePath, 'base64')
|
hasError.value = false
|
||||||
base64Image.value = `data:${window.node.mime.lookup(filePath) || 'image/png'};base64,${base64}`
|
}
|
||||||
isLoading.value = false
|
|
||||||
} catch (e) {
|
const handleImageError = () => {
|
||||||
console.log(e)
|
isLoading.value = false
|
||||||
hasError.value = true
|
hasError.value = true
|
||||||
isLoading.value = false
|
}
|
||||||
}
|
|
||||||
}
|
onBeforeMount(async () => {
|
||||||
|
await createBase64Image()
|
||||||
const handleImageLoad = () => {
|
})
|
||||||
isLoading.value = false
|
</script>
|
||||||
hasError.value = false
|
|
||||||
}
|
<style scoped>
|
||||||
|
.image-container {
|
||||||
const handleImageError = () => {
|
height: 100px;
|
||||||
isLoading.value = false
|
width: 100%;
|
||||||
hasError.value = true
|
margin: 0 auto;
|
||||||
}
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
onBeforeMount(async () => {
|
justify-content: center;
|
||||||
await createBase64Image()
|
position: relative;
|
||||||
})
|
}
|
||||||
</script>
|
|
||||||
|
.image {
|
||||||
<style scoped>
|
max-height: 100%;
|
||||||
.image-container {
|
max-width: 100%;
|
||||||
height: 100px;
|
object-fit: contain;
|
||||||
width: 100%;
|
display: block;
|
||||||
margin: 0 auto;
|
}
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
.loading-placeholder {
|
||||||
justify-content: center;
|
display: flex;
|
||||||
position: relative;
|
align-items: center;
|
||||||
}
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
.image {
|
height: 100%;
|
||||||
max-height: 100%;
|
}
|
||||||
max-width: 100%;
|
|
||||||
object-fit: contain;
|
.loading-spinner {
|
||||||
display: block;
|
width: 24px;
|
||||||
}
|
height: 24px;
|
||||||
|
border: 2px solid #e4e7ed;
|
||||||
.loading-placeholder {
|
border-top: 2px solid #409eff;
|
||||||
display: flex;
|
border-radius: 50%;
|
||||||
align-items: center;
|
animation: spin 1s linear infinite;
|
||||||
justify-content: center;
|
}
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
@keyframes spin {
|
||||||
}
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
.loading-spinner {
|
}
|
||||||
width: 24px;
|
100% {
|
||||||
height: 24px;
|
transform: rotate(360deg);
|
||||||
border: 2px solid #e4e7ed;
|
}
|
||||||
border-top: 2px solid #409eff;
|
}
|
||||||
border-radius: 50%;
|
</style>
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes spin {
|
|
||||||
0% { transform: rotate(0deg); }
|
|
||||||
100% { transform: rotate(360deg); }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,123 +1,123 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="image-container">
|
<div class="image-container">
|
||||||
<div
|
<div v-if="isLoading" class="loading-placeholder">
|
||||||
v-if="isLoading"
|
<div class="loading-spinner" />
|
||||||
class="loading-placeholder"
|
</div>
|
||||||
>
|
<img
|
||||||
<div class="loading-spinner" />
|
v-else-if="!hasError"
|
||||||
</div>
|
:src="imageSource"
|
||||||
<img
|
alt=""
|
||||||
v-else-if="!hasError"
|
class="image"
|
||||||
:src="imageSource"
|
@load="handleImageLoad"
|
||||||
alt=""
|
@error="handleImageError"
|
||||||
class="image"
|
/>
|
||||||
@load="handleImageLoad"
|
<img v-else :src="iconPath" alt="" class="image" />
|
||||||
@error="handleImageError"
|
</div>
|
||||||
>
|
</template>
|
||||||
<img
|
|
||||||
v-else
|
<script lang="ts" setup>
|
||||||
:src="iconPath"
|
import { computed, onMounted, ref, watch } from 'vue'
|
||||||
alt=""
|
|
||||||
class="image"
|
import { getFileIconPath } from '@/manage/utils/common'
|
||||||
>
|
import { IRPCActionType } from '@/utils/enum'
|
||||||
</div>
|
|
||||||
</template>
|
const preSignedUrl = ref('')
|
||||||
|
const isLoading = ref(true)
|
||||||
<script lang="ts" setup>
|
const hasError = ref(false)
|
||||||
import { computed, onMounted, ref, watch } from 'vue'
|
|
||||||
|
const props = defineProps<{
|
||||||
import { getFileIconPath } from '@/manage/utils/common'
|
item: {
|
||||||
import { IRPCActionType } from '@/utils/enum'
|
key: string
|
||||||
|
isImage: boolean
|
||||||
const preSignedUrl = ref('')
|
fileName: string | null | undefined
|
||||||
const isLoading = ref(true)
|
}
|
||||||
const hasError = ref(false)
|
alias: string
|
||||||
|
url: string
|
||||||
const props = defineProps<{
|
config: any
|
||||||
item: {
|
isShowThumbnail: boolean
|
||||||
key: string
|
}>()
|
||||||
isImage: boolean
|
|
||||||
fileName: string | null | undefined
|
const imageSource = computed(() => {
|
||||||
}
|
return props.isShowThumbnail && props.item.isImage
|
||||||
alias: string
|
? preSignedUrl.value
|
||||||
url: string
|
: `./assets/icons/${getFileIconPath(props.item.fileName ?? '')}`
|
||||||
config: any
|
})
|
||||||
isShowThumbnail: boolean
|
|
||||||
}>()
|
const iconPath = computed(() => `./assets/icons/${getFileIconPath(props.item.fileName ?? '')}`)
|
||||||
|
|
||||||
const imageSource = computed(() => {
|
async function getUrl() {
|
||||||
return props.isShowThumbnail && props.item.isImage
|
try {
|
||||||
? preSignedUrl.value
|
isLoading.value = true
|
||||||
: `./assets/icons/${getFileIconPath(props.item.fileName ?? '')}`
|
hasError.value = false
|
||||||
})
|
preSignedUrl.value = await window.electron.triggerRPC<any>(
|
||||||
|
IRPCActionType.MANAGE_GET_PRE_SIGNED_URL,
|
||||||
const iconPath = computed(() => `./assets/icons/${getFileIconPath(props.item.fileName ?? '')}`)
|
props.alias,
|
||||||
|
props.config
|
||||||
async function getUrl () {
|
)
|
||||||
try {
|
isLoading.value = false
|
||||||
isLoading.value = true
|
} catch (error) {
|
||||||
hasError.value = false
|
console.error('Failed to get pre-signed URL:', error)
|
||||||
preSignedUrl.value = await window.electron.triggerRPC<any>(IRPCActionType.MANAGE_GET_PRE_SIGNED_URL, props.alias, props.config)
|
hasError.value = true
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
} catch (error) {
|
}
|
||||||
console.error('Failed to get pre-signed URL:', error)
|
}
|
||||||
hasError.value = true
|
|
||||||
isLoading.value = false
|
const handleImageLoad = () => {
|
||||||
}
|
isLoading.value = false
|
||||||
}
|
hasError.value = false
|
||||||
|
}
|
||||||
const handleImageLoad = () => {
|
|
||||||
isLoading.value = false
|
const handleImageError = () => {
|
||||||
hasError.value = false
|
isLoading.value = false
|
||||||
}
|
hasError.value = true
|
||||||
|
}
|
||||||
const handleImageError = () => {
|
|
||||||
isLoading.value = false
|
watch(() => [props.url, props.item], getUrl, { deep: true })
|
||||||
hasError.value = true
|
|
||||||
}
|
onMounted(getUrl)
|
||||||
|
</script>
|
||||||
watch(() => [props.url, props.item], getUrl, { deep: true })
|
|
||||||
|
<style scoped>
|
||||||
onMounted(getUrl)
|
.image-container {
|
||||||
</script>
|
height: 100px;
|
||||||
|
width: 100%;
|
||||||
<style scoped>
|
margin: 0 auto;
|
||||||
.image-container {
|
display: flex;
|
||||||
height: 100px;
|
align-items: center;
|
||||||
width: 100%;
|
justify-content: center;
|
||||||
margin: 0 auto;
|
position: relative;
|
||||||
display: flex;
|
}
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
.image {
|
||||||
position: relative;
|
max-height: 100%;
|
||||||
}
|
max-width: 100%;
|
||||||
|
object-fit: contain;
|
||||||
.image {
|
display: block;
|
||||||
max-height: 100%;
|
}
|
||||||
max-width: 100%;
|
|
||||||
object-fit: contain;
|
.loading-placeholder {
|
||||||
display: block;
|
display: flex;
|
||||||
}
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
.loading-placeholder {
|
width: 100%;
|
||||||
display: flex;
|
height: 100%;
|
||||||
align-items: center;
|
}
|
||||||
justify-content: center;
|
|
||||||
width: 100%;
|
.loading-spinner {
|
||||||
height: 100%;
|
width: 24px;
|
||||||
}
|
height: 24px;
|
||||||
|
border: 2px solid #e4e7ed;
|
||||||
.loading-spinner {
|
border-top: 2px solid #409eff;
|
||||||
width: 24px;
|
border-radius: 50%;
|
||||||
height: 24px;
|
animation: spin 1s linear infinite;
|
||||||
border: 2px solid #e4e7ed;
|
}
|
||||||
border-top: 2px solid #409eff;
|
|
||||||
border-radius: 50%;
|
@keyframes spin {
|
||||||
animation: spin 1s linear infinite;
|
0% {
|
||||||
}
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
@keyframes spin {
|
100% {
|
||||||
0% { transform: rotate(0deg); }
|
transform: rotate(360deg);
|
||||||
100% { transform: rotate(360deg); }
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user