🚧 WIP: working on build-in sftp picbed

This commit is contained in:
萌萌哒赫萝 2023-08-05 04:59:10 -07:00
parent b882d42e10
commit bdc11dad43
12 changed files with 225 additions and 87 deletions

86
.github/workflows/mac_beta.yml vendored Normal file
View File

@ -0,0 +1,86 @@
# main.yml
# Workflow's name
name: Mac Beta Build
# Workflow's trigger
on:
workflow_dispatch:
env:
ELECTRON_OUTPUT_PATH: ./dist_electron
CSC_LINK: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
CSC_KEY_PASSWORD: ${{ secrets.P12_PASSWORD }}
jobs:
release:
name: build and release electron app
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-11]
steps:
- name: Check out git repository
uses: actions/checkout@v2
# step2: sign
- name: Install the Apple certificates
if: matrix.os == 'macos-11'
run: |
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
# step3: install node env
- name: Install Node.js
uses: actions/setup-node@v2
with:
node-version: '16.x'
- name: Install system deps
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils
# step3: yarn
- name: Yarn install macos
if: matrix.os == 'macos-11'
run: |
yarn
yarn global add xvfb-maybe
npm rebuild --platform=darwin --arch=arm64 sharp
- name: Yarn install windows
if: matrix.os == 'windows-latest'
run: |
yarn
yarn global add xvfb-maybe
- name: Yarn install linux
if: matrix.os == 'ubuntu-latest'
run: |
yarn
yarn global add xvfb-maybe
- name: Build & release app
run: |
yarn run build
yarn upload-beta
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
R2_SECRET_ID: ${{ secrets.R2_SECRET_ID }}
R2_SECRET_KEY: ${{ secrets.R2_SECRET_KEY }}
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
ELECTRON_SKIP_NOTARIZATION: ${{ secrets.ELECTRON_SKIP_NOTARIZATION }}
XCODE_APP_LOADER_EMAIL: ${{ secrets.XCODE_APP_LOADER_EMAIL }}
XCODE_APP_LOADER_PASSWORD: ${{ secrets.XCODE_APP_LOADER_PASSWORD }}
XCODE_TEAM_ID: ${{ secrets.XCODE_TEAM_ID }}
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}

View File

@ -1,52 +0,0 @@
# Commented sections below can be used to run tests on the CI server
# https://simulatedgreg.gitbooks.io/electron-vue/content/en/testing.html#on-the-subject-of-ci-testing
osx_image: xcode8.3
sudo: required
dist: trusty
language: c
matrix:
include:
- os: osx
- os: linux
env: CC=clang CXX=clang++ npm_config_clang=1
compiler: clang
cache:
directories:
- node_modules
- "$HOME/.electron"
- "$HOME/.cache"
addons:
apt:
packages:
- libgnome-keyring-dev
- icnsutils
#- xvfb
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install git-lfs; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils; fi
install:
#- export DISPLAY=':99.0'
#- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
- nvm install 10
- curl -o- -L https://yarnpkg.com/install.sh | bash
- source ~/.bashrc
- npm install -g xvfb-maybe
- yarn
script:
#- xvfb-maybe node_modules/.bin/karma start test/unit/karma.conf.js
#- yarn run pack && xvfb-maybe node_modules/.bin/mocha test/e2e
- npm run release
# - yarn run build:docs
before_script:
- git lfs pull
branches:
only:
- master
# after_script:
# - cd docs/dist
# - git init
# - git config user.name "Molunerfinn"
# - git config user.email "marksz@teamsz.xyz"
# - git add .
# - git commit -m "Travis build docs"
# - git push --force --quiet "https://${GH_TOKEN}@github.com/Molunerfinn/PicGo.git" master:gh-pages

View File

@ -65,8 +65,9 @@
"marked": "^4.3.0",
"mime-types": "^2.1.35",
"mitt": "^3.0.0",
"node-ssh-no-cpu-features": "^1.0.1",
"nodejs-file-downloader": "^4.12.1",
"piclist": "^0.8.7",
"piclist": "^0.8.10",
"pinia": "^2.1.4",
"pinia-plugin-persistedstate": "^3.1.0",
"qiniu": "^7.9.0",
@ -120,6 +121,7 @@
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-vue": "^9.9.0",
"husky": "^3.1.0",
"node-loader": "^2.0.0",
"stylus": "^0.54.7",
"stylus-loader": "^3.0.2",
"typescript": "^4.9.5",

View File

@ -35,7 +35,8 @@ app.config.globalProperties.$builtInPicBed = [
'aliyun',
'github',
'webdavplist',
'local'
'local',
'sftpplist'
]
app.config.unwrapInjectedRef = true

View File

@ -44,6 +44,8 @@ import { buildMainPageMenu, buildMiniPageMenu, buildPluginPageMenu, buildPicBedL
import path from 'path'
import { T } from '~/main/i18n'
import { uploadFile, downloadFile } from '../utils/syncSettings'
import SSHClient from '../utils/sshClient'
import { ISftpPlistConfig } from 'piclist'
const STORE_PATH = app.getPath('userData')
@ -120,6 +122,21 @@ export default {
}
})
ipcMain.handle('delete-sftp-file', async (_evt: IpcMainInvokeEvent, config: ISftpPlistConfig, fileName: string) => {
try {
const client = SSHClient.instance
await client.connect(config)
const uploadPath = `/${(config.uploadPath || '').replace(/^\/+|\/+$/g, '')}/`.replace(/\/+/g, '/')
const remote = path.join(uploadPath, fileName)
const deleteResult = await client.deleteFile(remote)
client.close()
return deleteResult
} catch (err: any) {
console.error(err)
return false
}
})
ipcMain.handle('migrateFromPicGo', async () => {
const picGoConfigPath = STORE_PATH.replace('piclist', 'picgo')
const fileToMigration = [

View File

@ -0,0 +1,64 @@
import { NodeSSH, Config } from 'node-ssh-no-cpu-features'
import { ISftpPlistConfig } from 'piclist/dist/types'
class SSHClient {
// eslint-disable-next-line no-use-before-define
private static _instance: SSHClient
private static _client: NodeSSH
private _isConnected = false
public static get instance (): SSHClient {
return this._instance || (this._instance = new this())
}
public static get client (): NodeSSH {
return this._client || (this._client = new NodeSSH())
}
private changeWinStylePathToUnix (path: string): string {
return path.replace(/\\/g, '/')
}
public async connect (config: ISftpPlistConfig): Promise<boolean> {
const { username, password, privateKey, passphrase } = config
const loginInfo: Config = privateKey
? { username, privateKeyPath: privateKey, passphrase: passphrase || undefined }
: { username, password }
try {
await SSHClient.client.connect({
host: config.host,
port: Number(config.port) || 22,
...loginInfo
})
this._isConnected = true
return true
} catch (err: any) {
throw new Error(err)
}
}
public async deleteFile (remote: string): Promise<boolean> {
if (!this._isConnected) {
throw new Error('SSH 未连接')
}
try {
remote = this.changeWinStylePathToUnix(remote)
const script = `rm -f ${remote}`
return await this.exec(script)
} catch (err: any) {
return false
}
}
private async exec (script: string): Promise<boolean> {
const execResult = await SSHClient.client.execCommand(script)
return execResult.code === 0
}
public close (): void {
SSHClient.client.dispose()
this._isConnected = false
}
}
export default SSHClient

View File

@ -8,6 +8,7 @@ import UpyunApi from './upyun'
import AwsS3Api from './awss3'
import WebdavApi from './webdav'
import LocalApi from './local'
import SftpPlistApi from './sftpplist'
const apiMap: IStringKeyMap = {
smms: SmmsApi,
@ -19,7 +20,8 @@ const apiMap: IStringKeyMap = {
upyun: UpyunApi,
'aws-s3': AwsS3Api,
webdavplist: WebdavApi,
local: LocalApi
local: LocalApi,
sftpplist: SftpPlistApi
}
export default class ALLApi {

View File

@ -0,0 +1,18 @@
import { ipcRenderer } from 'electron'
import { getRawData } from '~/renderer/utils/common'
export default class SftpPlistApi {
static async delete (configMap: IStringKeyMap): Promise<boolean> {
const { fileName, config } = configMap
try {
const deleteResult = await ipcRenderer.invoke('delete-sftp-file',
getRawData(config),
fileName
)
return deleteResult
} catch (error) {
console.error(error)
return false
}
}
}

View File

@ -664,7 +664,7 @@ function remove (item: ImgInfo) {
type: 'warning'
}).then(async () => {
const file = await $$db.getById(item.id!)
const picBedsCanbeDeleted = ['smms', 'github', 'imgur', 'tcyun', 'aliyun', 'qiniu', 'upyun', 'aws-s3', 'webdavplist', 'local']
const picBedsCanbeDeleted = ['smms', 'github', 'imgur', 'tcyun', 'aliyun', 'qiniu', 'upyun', 'aws-s3', 'webdavplist', 'local', 'sftpplist']
if (await getConfig('settings.deleteCloudFile')) {
if (item.type !== undefined && picBedsCanbeDeleted.includes(item.type)) {
const result = await ALLApi.delete(item)
@ -774,7 +774,7 @@ function multiRemove () {
const files: IResult<ImgInfo>[] = []
const imageIDList = Object.keys(choosedList)
const isDeleteCloudFile = await getConfig('settings.deleteCloudFile')
const picBedsCanbeDeleted = ['smms', 'github', 'imgur', 'tcyun', 'aliyun', 'qiniu', 'upyun', 'aws-s3', 'webdavplist', 'local']
const picBedsCanbeDeleted = ['smms', 'github', 'imgur', 'tcyun', 'aliyun', 'qiniu', 'upyun', 'aws-s3', 'webdavplist', 'local', 'sftpplist']
if (isDeleteCloudFile) {
for (let i = 0; i < imageIDList.length; i++) {
const key = imageIDList[i]

View File

@ -1448,6 +1448,7 @@
</div>
</template>
<script lang="ts" setup>
// @ts-ignore
import { ElForm, ElMessage as $message, ElMessage, ElMessageBox, FormRules } from 'element-plus'
import { Reading, Close, Edit, InfoFilled } from '@element-plus/icons-vue'
import pkg from 'root/package.json'

View File

@ -36,6 +36,12 @@ const config = {
.clear()
.add('main') // fix some modules will use browser target
.add('module')
config.module
.rule('node')
.test(/\.node$/)
.use('node-loader')
.loader('node-loader')
.end()
},
builderOptions: {
productName: 'PicList',

View File

@ -3229,7 +3229,7 @@
dependencies:
"@types/node" "*"
"@types/ssh2@^1.11.9":
"@types/ssh2@^1.11.10":
version "1.11.13"
resolved "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.11.13.tgz#e6224da936abec0541bf26aa826b1cc37ea70d69"
integrity sha512-08WbG68HvQ2YVi74n2iSUnYHYpUdFc/s2IsI0BHBdJwaqYJpWlVv9elL0tYShTv60yr0ObdxJR5NrCRiGJ/0CQ==
@ -4857,11 +4857,6 @@ buffer@^5.1.0, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0:
base64-js "^1.3.1"
ieee754 "^1.1.13"
buildcheck@~0.0.6:
version "0.0.6"
resolved "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz#89aa6e417cfd1e2196e3f8fe915eb709d2fe4238"
integrity sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==
builder-util-runtime@9.0.3:
version "9.0.3"
resolved "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.0.3.tgz#6c62c493ba2b73c2af92432db4013b5a327f02b2"
@ -5850,14 +5845,6 @@ cosmiconfig@^7, cosmiconfig@^7.0.0:
path-type "^4.0.0"
yaml "^1.10.0"
cpu-features@~0.0.8:
version "0.0.8"
resolved "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.8.tgz#a2d464b023b8ad09004c8cdca23b33f192f63546"
integrity sha512-BbHBvtYhUhksqTjr6bhNOjGgMnhwhGTQmOoZGD+K7BCaQDCuZl/Ve1ZxUSMRwVC4D/rkCPQ2MAIeYzrWyK7eEg==
dependencies:
buildcheck "~0.0.6"
nan "^2.17.0"
crc32@^0.2.2:
version "0.2.2"
resolved "https://registry.npmjs.org/crc32/-/crc32-0.2.2.tgz#7ad220d6ffdcd119f9fc127a7772cacea390a4ba"
@ -10456,6 +10443,13 @@ node-forge@^1:
resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
node-loader@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/node-loader/-/node-loader-2.0.0.tgz#9109a6d828703fd3e0aa03c1baec12a798071562"
integrity sha512-I5VN34NO4/5UYJaUBtkrODPWxbobrE4hgDqPrjB25yPkonFhCmZ146vTH+Zg417E9Iwoh1l/MbRs1apc5J295Q==
dependencies:
loader-utils "^2.0.0"
node-releases@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5"
@ -10466,18 +10460,18 @@ node-releases@^2.0.6:
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz#0f349cdc8fcfa39a92ac0be9bc48b7706292b9ae"
integrity sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==
node-ssh@^13.1.0:
version "13.1.0"
resolved "https://registry.npmjs.org/node-ssh/-/node-ssh-13.1.0.tgz#fca947200d61db9a5f9915e27c252e133b79e6bf"
integrity sha512-GLcw49yFd9+rUpP+FgX6wrF/N90cmuDl2n0i8d3L828b6riRjkb9w3SS+XvviRWbrAhLxuMKywFqxvQDZQ1bug==
node-ssh-no-cpu-features@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/node-ssh-no-cpu-features/-/node-ssh-no-cpu-features-1.0.1.tgz#e0a54fa16d34f44dfa307b1c52d592d4b891e65c"
integrity sha512-dfxNdHpeB2Yapskc5PBZCnhRmL1bdOYZX/N9PECR0d1I8U2PlPB4VfshmNJIw/l3BuGNhFquu5Tu6z/1lnWmIA==
dependencies:
"@types/ssh2" "^1.11.9"
"@types/ssh2" "^1.11.10"
is-stream "^2.0.0"
make-dir "^3.1.0"
sb-promise-queue "^2.1.0"
sb-scandir "^3.1.0"
shell-escape "^0.2.0"
ssh2 "^1.11.0"
ssh2-no-cpu-features "^1.0.0"
nodejs-file-downloader@^4.12.1:
version "4.12.1"
@ -11054,10 +11048,10 @@ performance-now@^2.1.0:
resolved "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==
piclist@^0.8.7:
version "0.8.7"
resolved "https://registry.npmjs.org/piclist/-/piclist-0.8.7.tgz#9a4fb342d70cfe28513b6df218370b05b8e9b170"
integrity sha512-IYVh+E9V7DyikmYZgE8ylWdCqg6aQQ+rb+y6oNTYo2tFWx6pdfthG9LdWAl6V9Uf+Y2Wt9nsC0XNi4V3ORlb3g==
piclist@^0.8.10:
version "0.8.10"
resolved "https://registry.npmjs.org/piclist/-/piclist-0.8.10.tgz#efd7eddbe66023f375a7d687d4466a9031999aea"
integrity sha512-VLoLZywOoV6lGJN8u8Llr6B63OzT8k8yE5QF40JV3nwNK1jyGRLRZ/57/HIXsGFojWgoDerj3hmVuJOX556NFA==
dependencies:
"@picgo/i18n" "^1.0.0"
"@picgo/store" "^2.0.4"
@ -11082,7 +11076,7 @@ piclist@^0.8.7:
mime-types "2.1.33"
minimatch "^3.0.4"
minimist "^1.2.5"
node-ssh "^13.1.0"
node-ssh-no-cpu-features "^1.0.1"
qiniu "^7.8.0"
resolve "^1.8.1"
rimraf "^3.0.2"
@ -12809,15 +12803,14 @@ sprintf-js@~1.0.2:
resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
ssh2@^1.11.0:
version "1.14.0"
resolved "https://registry.npmjs.org/ssh2/-/ssh2-1.14.0.tgz#8f68440e1b768b66942c9e4e4620b2725b3555bb"
integrity sha512-AqzD1UCqit8tbOKoj6ztDDi1ffJZ2rV2SwlgrVVrHPkV5vWqGJOVp5pmtj18PunkPJAuKQsnInyKV+/Nb2bUnA==
ssh2-no-cpu-features@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/ssh2-no-cpu-features/-/ssh2-no-cpu-features-1.0.0.tgz#641a8ea5331638ea9bfdee9e53f38ebfc46bf8cf"
integrity sha512-94HbS6PbjOvGYnWQ0OFlGLWp3yw6BfSAmpVlCRvsqqyfWa86gCorpnXFJLLJklnfCbp6UiZhEKzm3W+8vKCHqw==
dependencies:
asn1 "^0.2.6"
bcrypt-pbkdf "^1.0.2"
optionalDependencies:
cpu-features "~0.0.8"
nan "^2.17.0"
sshpk@^1.7.0: