mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-05-16 08:57:36 +08:00
🎨 Style(custom): format with prettier
This commit is contained in:
@@ -8,7 +8,7 @@ import { DEFAULT_AES_PASSWORD } from '#/utils/static'
|
||||
export class AESHelper {
|
||||
key: Buffer
|
||||
|
||||
constructor () {
|
||||
constructor() {
|
||||
const userPassword = picgo.getConfig<string>(configPaths.settings.aesPassword) || DEFAULT_AES_PASSWORD
|
||||
const fixedSalt = Buffer.from('a8b3c4d2e4f5098712345678feedc0de', 'hex')
|
||||
const fixedIterations = 100000
|
||||
@@ -16,7 +16,7 @@ export class AESHelper {
|
||||
this.key = crypto.pbkdf2Sync(userPassword, fixedSalt, fixedIterations, keyLength, 'sha512')
|
||||
}
|
||||
|
||||
encrypt (plainText: string) {
|
||||
encrypt(plainText: string) {
|
||||
const iv = crypto.randomBytes(16)
|
||||
const cipher = crypto.createCipheriv('aes-256-cbc', this.key, iv)
|
||||
let encrypted = cipher.update(plainText, 'utf8', 'hex')
|
||||
@@ -24,7 +24,7 @@ export class AESHelper {
|
||||
return `${iv.toString('hex')}:${encrypted}`
|
||||
}
|
||||
|
||||
decrypt (encryptedData: string) {
|
||||
decrypt(encryptedData: string) {
|
||||
const [ivHex, encryptedText] = encryptedData.split(':')
|
||||
if (!ivHex || !encryptedText) {
|
||||
return '{}'
|
||||
|
||||
@@ -10,7 +10,7 @@ import { i18nManager } from '~/i18n'
|
||||
const configPath = dbPathChecker()
|
||||
const CONFIG_DIR = path.dirname(configPath)
|
||||
|
||||
function beforeOpen () {
|
||||
function beforeOpen() {
|
||||
if (process.platform === 'darwin') {
|
||||
resolveMacWorkFlow()
|
||||
}
|
||||
@@ -18,10 +18,7 @@ function beforeOpen () {
|
||||
resolveOtherI18nFiles()
|
||||
}
|
||||
|
||||
function copyFileOutsideOfElectronAsar (
|
||||
sourceInAsarArchive: string,
|
||||
destOutsideAsarArchive: string
|
||||
) {
|
||||
function copyFileOutsideOfElectronAsar(sourceInAsarArchive: string, destOutsideAsarArchive: string) {
|
||||
if (fs.existsSync(sourceInAsarArchive)) {
|
||||
// file will be copied
|
||||
if (fs.statSync(sourceInAsarArchive).isFile()) {
|
||||
@@ -45,7 +42,7 @@ function copyFileOutsideOfElectronAsar (
|
||||
/**
|
||||
* macOS 右键菜单
|
||||
*/
|
||||
function resolveMacWorkFlow () {
|
||||
function resolveMacWorkFlow() {
|
||||
const dest = `${os.homedir()}/Library/Services/Upload pictures with PicList.workflow`
|
||||
if (fs.existsSync(dest)) return true
|
||||
try {
|
||||
@@ -55,7 +52,7 @@ function resolveMacWorkFlow () {
|
||||
}
|
||||
}
|
||||
|
||||
function diffFilesAndUpdate (filePath1: string, filePath2: string) {
|
||||
function diffFilesAndUpdate(filePath1: string, filePath2: string) {
|
||||
try {
|
||||
const file1 = fs.existsSync(filePath1) && fs.readFileSync(filePath1)
|
||||
const file2 = fs.existsSync(filePath1) && fs.readFileSync(filePath2)
|
||||
@@ -72,7 +69,7 @@ function diffFilesAndUpdate (filePath1: string, filePath2: string) {
|
||||
/**
|
||||
* 初始化剪贴板生成图片的脚本
|
||||
*/
|
||||
function resolveClipboardImageGenerator () {
|
||||
function resolveClipboardImageGenerator() {
|
||||
const clipboardFiles = getClipboardFiles()
|
||||
if (!fs.pathExistsSync(path.join(CONFIG_DIR, 'windows10.ps1'))) {
|
||||
clipboardFiles.forEach(item => {
|
||||
@@ -84,14 +81,8 @@ function resolveClipboardImageGenerator () {
|
||||
})
|
||||
}
|
||||
|
||||
function getClipboardFiles () {
|
||||
const files = [
|
||||
'/linux.sh',
|
||||
'/mac.applescript',
|
||||
'/windows.ps1',
|
||||
'/windows10.ps1',
|
||||
'/wsl.sh'
|
||||
]
|
||||
function getClipboardFiles() {
|
||||
const files = ['/linux.sh', '/mac.applescript', '/windows.ps1', '/windows10.ps1', '/wsl.sh']
|
||||
|
||||
return files.map(item => {
|
||||
return {
|
||||
@@ -105,7 +96,7 @@ function resolveClipboardImageGenerator () {
|
||||
/**
|
||||
* 初始化其他语言文件
|
||||
*/
|
||||
function resolveOtherI18nFiles () {
|
||||
function resolveOtherI18nFiles() {
|
||||
const i18nFolder = path.join(CONFIG_DIR, 'i18n')
|
||||
if (!fs.pathExistsSync(i18nFolder)) {
|
||||
fs.mkdirSync(i18nFolder)
|
||||
|
||||
@@ -8,13 +8,13 @@ class ClipboardWatcher extends EventEmitter {
|
||||
timer: NodeJS.Timeout | null
|
||||
lastImageHash: string | null
|
||||
|
||||
constructor () {
|
||||
constructor() {
|
||||
super()
|
||||
this.lastImageHash = null
|
||||
this.timer = null
|
||||
}
|
||||
|
||||
startListening (watchDelay = 500) {
|
||||
startListening(watchDelay = 500) {
|
||||
this.stopListening(false)
|
||||
|
||||
this.timer = setInterval(() => {
|
||||
@@ -33,7 +33,7 @@ class ClipboardWatcher extends EventEmitter {
|
||||
logger.info('Start to watch clipboard')
|
||||
}
|
||||
|
||||
stopListening (isLog = true) {
|
||||
stopListening(isLog = true) {
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
@@ -42,7 +42,7 @@ class ClipboardWatcher extends EventEmitter {
|
||||
isLog && logger.info('Stop to watch clipboard')
|
||||
}
|
||||
|
||||
getImageHash (image: Electron.NativeImage): string {
|
||||
getImageHash(image: Electron.NativeImage): string {
|
||||
const buffer = image.toBitmap()
|
||||
return crypto.createHash('md5').update(buffer).digest('hex')
|
||||
}
|
||||
|
||||
@@ -12,11 +12,13 @@ import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
export let tray: Tray
|
||||
|
||||
export const setTray = (t: Tray) => { tray = t }
|
||||
export const setTray = (t: Tray) => {
|
||||
tray = t
|
||||
}
|
||||
|
||||
export const getTray = () => tray
|
||||
|
||||
export function setTrayToolTip (title: string): void {
|
||||
export function setTrayToolTip(title: string): void {
|
||||
if (tray) {
|
||||
tray.setToolTip(title)
|
||||
}
|
||||
@@ -32,13 +34,15 @@ export const handleCopyUrl = (str: string): void => {
|
||||
* show notification
|
||||
* @param options
|
||||
*/
|
||||
export const showNotification = (options: IPrivateShowNotificationOption = {
|
||||
title: '',
|
||||
body: '',
|
||||
clickToCopy: false,
|
||||
copyContent: '',
|
||||
clickFn: () => {}
|
||||
}) => {
|
||||
export const showNotification = (
|
||||
options: IPrivateShowNotificationOption = {
|
||||
title: '',
|
||||
body: '',
|
||||
clickToCopy: false,
|
||||
copyContent: '',
|
||||
clickFn: () => {}
|
||||
}
|
||||
) => {
|
||||
const notification = new Notification({
|
||||
title: options.title,
|
||||
body: options.body
|
||||
@@ -60,10 +64,8 @@ export const showNotification = (options: IPrivateShowNotificationOption = {
|
||||
}
|
||||
|
||||
export const showMessageBox = (options: any) => {
|
||||
return new Promise<IShowMessageBoxResult>(async (resolve) => {
|
||||
dialog.showMessageBox(
|
||||
options
|
||||
).then((res) => {
|
||||
return new Promise<IShowMessageBoxResult>(async resolve => {
|
||||
dialog.showMessageBox(options).then(res => {
|
||||
resolve({
|
||||
result: res.response,
|
||||
checkboxChecked: res.checkboxChecked
|
||||
@@ -118,14 +120,18 @@ export const getClipboardFilePath = (): string => {
|
||||
}
|
||||
|
||||
if (img.isEmpty() && platform === 'win32') {
|
||||
const imgPath = clipboard.readBuffer('FileNameW')?.toString('ucs2')?.replace(RegExp(String.fromCharCode(0), 'g'), '')
|
||||
const imgPath = clipboard
|
||||
.readBuffer('FileNameW')
|
||||
?.toString('ucs2')
|
||||
?.replace(RegExp(String.fromCharCode(0), 'g'), '')
|
||||
return imgPath || ''
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
export const handleUrlEncodeWithSetting = (url: string) => db.get(configPaths.settings.encodeOutputURL) ? handleUrlEncode(url) : url
|
||||
export const handleUrlEncodeWithSetting = (url: string) =>
|
||||
db.get(configPaths.settings.encodeOutputURL) ? handleUrlEncode(url) : url
|
||||
|
||||
const c1nApi = 'https://c1n.cn/link/short'
|
||||
|
||||
@@ -163,7 +169,12 @@ const generateYOURLSShortUrl = async (url: string) => {
|
||||
if (!/^https?:\/\//.test(domain)) {
|
||||
domain = `http://${domain}`
|
||||
}
|
||||
const params = new URLSearchParams({ signature, action: 'shorturl', format: 'json', url })
|
||||
const params = new URLSearchParams({
|
||||
signature,
|
||||
action: 'shorturl',
|
||||
format: 'json',
|
||||
url
|
||||
})
|
||||
try {
|
||||
const res = await axios.get(`${domain}/yourls-api.php?${params.toString()}`)
|
||||
if (res.data?.shorturl) {
|
||||
|
||||
@@ -32,7 +32,7 @@ const dogeRegionMap: IStringKeyMap = {
|
||||
'ap-chengdu': '3'
|
||||
}
|
||||
|
||||
async function dogecloudApi (
|
||||
async function dogecloudApi(
|
||||
apiPath: string,
|
||||
data = {},
|
||||
jsonMode: boolean = false,
|
||||
@@ -40,7 +40,10 @@ async function dogecloudApi (
|
||||
secretKey: string
|
||||
) {
|
||||
const body = jsonMode ? JSON.stringify(data) : querystring.encode(data)
|
||||
const sign = crypto.createHmac('sha1', secretKey).update(Buffer.from(apiPath + '\n' + body, 'utf8')).digest('hex')
|
||||
const sign = crypto
|
||||
.createHmac('sha1', secretKey)
|
||||
.update(Buffer.from(apiPath + '\n' + body, 'utf8'))
|
||||
.digest('hex')
|
||||
const authorization = `TOKEN ${accessKey}:${sign}`
|
||||
try {
|
||||
const res = await axios.request({
|
||||
@@ -62,12 +65,18 @@ async function dogecloudApi (
|
||||
}
|
||||
}
|
||||
|
||||
async function getDogeToken (accessKey: string, secretKey: string): Promise<{} | DogecloudTokenFull> {
|
||||
async function getDogeToken(accessKey: string, secretKey: string): Promise<IObj | DogecloudTokenFull> {
|
||||
try {
|
||||
const data = await dogecloudApi('/auth/tmp_token.json', {
|
||||
channel: 'OSS_FULL',
|
||||
scopes: ['*']
|
||||
}, true, accessKey, secretKey)
|
||||
const data = await dogecloudApi(
|
||||
'/auth/tmp_token.json',
|
||||
{
|
||||
channel: 'OSS_FULL',
|
||||
scopes: ['*']
|
||||
},
|
||||
true,
|
||||
accessKey,
|
||||
secretKey
|
||||
)
|
||||
return data
|
||||
} catch (err: any) {
|
||||
console.log(err)
|
||||
@@ -75,10 +84,17 @@ async function getDogeToken (accessKey: string, secretKey: string): Promise<{} |
|
||||
}
|
||||
}
|
||||
|
||||
export async function removeFileFromS3InMain (configMap: IStringKeyMap, dogeMode: boolean = false) {
|
||||
export async function removeFileFromS3InMain(configMap: IStringKeyMap, dogeMode: boolean = false) {
|
||||
try {
|
||||
const { url: rawUrl, type, config: { accessKeyID, secretAccessKey, bucketName, endpoint, pathStyleAccess, rejectUnauthorized, proxy } } = configMap
|
||||
let { imgUrl, config: { region } } = configMap
|
||||
const {
|
||||
url: rawUrl,
|
||||
type,
|
||||
config: { accessKeyID, secretAccessKey, bucketName, endpoint, pathStyleAccess, rejectUnauthorized, proxy }
|
||||
} = configMap
|
||||
let {
|
||||
imgUrl,
|
||||
config: { region }
|
||||
} = configMap
|
||||
if (type === 'aws-s3' || type === 'aws-s3-plist') {
|
||||
imgUrl = rawUrl || imgUrl || ''
|
||||
}
|
||||
@@ -105,21 +121,21 @@ export async function removeFileFromS3InMain (configMap: IStringKeyMap, dogeMode
|
||||
const extraOptions = sslEnabled ? { rejectUnauthorized: !!rejectUnauthorized } : {}
|
||||
const handler = sslEnabled
|
||||
? new NodeHttpHandler({
|
||||
httpsAgent: agent.https
|
||||
? agent.https
|
||||
: new https.Agent({
|
||||
...commonOptions,
|
||||
...extraOptions
|
||||
})
|
||||
})
|
||||
httpsAgent: agent.https
|
||||
? agent.https
|
||||
: new https.Agent({
|
||||
...commonOptions,
|
||||
...extraOptions
|
||||
})
|
||||
})
|
||||
: new NodeHttpHandler({
|
||||
httpAgent: agent.http
|
||||
? agent.http
|
||||
: new http.Agent({
|
||||
...commonOptions,
|
||||
...extraOptions
|
||||
})
|
||||
})
|
||||
httpAgent: agent.http
|
||||
? agent.http
|
||||
: new http.Agent({
|
||||
...commonOptions,
|
||||
...extraOptions
|
||||
})
|
||||
})
|
||||
const s3Options: S3ClientConfig = {
|
||||
credentials: {
|
||||
accessKeyId: accessKeyID,
|
||||
@@ -162,10 +178,12 @@ export async function removeFileFromS3InMain (configMap: IStringKeyMap, dogeMode
|
||||
}
|
||||
}
|
||||
|
||||
export async function removeFileFromDogeInMain (configMap: IStringKeyMap) {
|
||||
export async function removeFileFromDogeInMain(configMap: IStringKeyMap) {
|
||||
try {
|
||||
const { config: { bucketName, AccessKey, SecretKey } } = configMap
|
||||
const token = await getDogeToken(AccessKey, SecretKey) as DogecloudTokenFull
|
||||
const {
|
||||
config: { bucketName, AccessKey, SecretKey }
|
||||
} = configMap
|
||||
const token = (await getDogeToken(AccessKey, SecretKey)) as DogecloudTokenFull
|
||||
const bucket = token.Buckets?.find(item => item.name === bucketName || item.s3Bucket === bucketName)
|
||||
const newConfigMap = Object.assign({}, configMap)
|
||||
newConfigMap.config = {
|
||||
@@ -184,7 +202,7 @@ export async function removeFileFromDogeInMain (configMap: IStringKeyMap) {
|
||||
}
|
||||
}
|
||||
|
||||
function createHuaweiAuthorization (
|
||||
function createHuaweiAuthorization(
|
||||
bucketName: string,
|
||||
path: string,
|
||||
fileName: string,
|
||||
@@ -197,7 +215,7 @@ function createHuaweiAuthorization (
|
||||
return `OBS ${accessKey}:${singature}`
|
||||
}
|
||||
|
||||
export async function removeFileFromHuaweiInMain (configMap: IStringKeyMap) {
|
||||
export async function removeFileFromHuaweiInMain(configMap: IStringKeyMap) {
|
||||
const { fileName, config } = configMap
|
||||
const { accessKeyId, accessKeySecret, bucketName, endpoint } = config
|
||||
let path = config.path || '/'
|
||||
@@ -223,11 +241,11 @@ export async function removeFileFromHuaweiInMain (configMap: IStringKeyMap) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function removeFileFromSFTPInMain (config: ISftpPlistConfig, fileName: string) {
|
||||
export async function removeFileFromSFTPInMain(config: ISftpPlistConfig, fileName: string) {
|
||||
try {
|
||||
const client = SSHClient.instance
|
||||
await client.connect(config)
|
||||
const uploadPath = `/${(config.uploadPath || '')}/`.replace(/\/+/g, '/')
|
||||
const uploadPath = `/${config.uploadPath || ''}/`.replace(/\/+/g, '/')
|
||||
const remote = path.join(uploadPath, fileName)
|
||||
const deleteResult = await client.deleteFileSFTP(config, remote)
|
||||
client.close()
|
||||
|
||||
@@ -9,11 +9,8 @@ export const isMacOS = process.platform === 'darwin'
|
||||
|
||||
let version: string | undefined
|
||||
|
||||
const clean = (version: string) => version.split('.').length === 1
|
||||
? `${version}.0.0`
|
||||
: version.split('.').length === 2
|
||||
? `${version}.0`
|
||||
: version
|
||||
const clean = (version: string) =>
|
||||
version.split('.').length === 1 ? `${version}.0.0` : version.split('.').length === 2 ? `${version}.0` : version
|
||||
|
||||
const parseVersion = (plist: string) => {
|
||||
const matches = /<key>ProductVersion<\/key>\s*<string>([\d.]+)<\/string>/.exec(plist)
|
||||
@@ -24,7 +21,7 @@ const parseVersion = (plist: string) => {
|
||||
return matches[1].replace('10.16', '11')
|
||||
}
|
||||
|
||||
export function macOSVersion (): string {
|
||||
export function macOSVersion(): string {
|
||||
if (!isMacOS) return ''
|
||||
|
||||
if (!version) {
|
||||
@@ -45,7 +42,7 @@ if (process.env.NODE_ENV === 'test') {
|
||||
macOSVersion._parseVersion = parseVersion
|
||||
}
|
||||
|
||||
export function isMacOSVersion (semverRange: string) {
|
||||
export function isMacOSVersion(semverRange: string) {
|
||||
if (!isMacOS) {
|
||||
return false
|
||||
}
|
||||
@@ -55,7 +52,7 @@ export function isMacOSVersion (semverRange: string) {
|
||||
return semver.satisfies(macOSVersion(), clean(semverRange))
|
||||
}
|
||||
|
||||
export function isMacOSVersionGreaterThanOrEqualTo (version: string) {
|
||||
export function isMacOSVersionGreaterThanOrEqualTo(version: string) {
|
||||
if (!isMacOS) {
|
||||
return false
|
||||
}
|
||||
@@ -65,7 +62,7 @@ export function isMacOSVersionGreaterThanOrEqualTo (version: string) {
|
||||
return semver.gte(macOSVersion(), clean(version))
|
||||
}
|
||||
|
||||
export function assertMacOSVersion (semverRange: string) {
|
||||
export function assertMacOSVersion(semverRange: string) {
|
||||
semverRange = semverRange.replace('10.16', '11')
|
||||
|
||||
if (!isMacOSVersion(semverRange)) {
|
||||
@@ -73,7 +70,7 @@ export function assertMacOSVersion (semverRange: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function assertMacOSVersionGreaterThanOrEqualTo (version: string) {
|
||||
export function assertMacOSVersionGreaterThanOrEqualTo(version: string) {
|
||||
version = version.replace('10.16', '11')
|
||||
|
||||
if (!isMacOSVersionGreaterThanOrEqualTo(version)) {
|
||||
@@ -81,7 +78,7 @@ export function assertMacOSVersionGreaterThanOrEqualTo (version: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function assertMacOS () {
|
||||
export function assertMacOS() {
|
||||
if (!isMacOS) {
|
||||
throw new Error('Requires macOS')
|
||||
}
|
||||
|
||||
@@ -4,19 +4,21 @@ import { configPaths } from '#/utils/configPaths'
|
||||
const getPicBeds = () => {
|
||||
const picBedTypes = picgo.helper.uploader.getIdList()
|
||||
const picBedFromDB = picgo.getConfig<IPicBedType[]>(configPaths.picBed.list) || []
|
||||
const picBeds = picBedTypes.map((item: string) => {
|
||||
const visible = picBedFromDB.find((i: IPicBedType) => i.type === item) // object or undefined
|
||||
return {
|
||||
type: item,
|
||||
name: picgo.helper.uploader.get(item)!.name || item,
|
||||
visible: visible ? visible.visible : true
|
||||
}
|
||||
}).sort((a) => {
|
||||
if (a.type === 'tcyun') {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}) as IPicBedType[]
|
||||
const picBeds = picBedTypes
|
||||
.map((item: string) => {
|
||||
const visible = picBedFromDB.find((i: IPicBedType) => i.type === item) // object or undefined
|
||||
return {
|
||||
type: item,
|
||||
name: picgo.helper.uploader.get(item)!.name || item,
|
||||
visible: visible ? visible.visible : true
|
||||
}
|
||||
})
|
||||
.sort(a => {
|
||||
if (a.type === 'tcyun') {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}) as IPicBedType[]
|
||||
return picBeds
|
||||
}
|
||||
|
||||
|
||||
@@ -36,34 +36,34 @@ const getUploadFiles = (argv = process.argv, cwd = process.cwd(), logger: Logger
|
||||
if (fileList?.length === 0) {
|
||||
return null // for uploading images in clipboard
|
||||
} else if ((fileList?.length || 0) > 0) {
|
||||
const result = fileList!.map(item => {
|
||||
if (isUrl(item)) {
|
||||
return {
|
||||
path: item
|
||||
}
|
||||
}
|
||||
if (path.isAbsolute(item)) {
|
||||
return {
|
||||
path: item
|
||||
}
|
||||
} else {
|
||||
const tempPath = path.join(cwd, item)
|
||||
if (fs.existsSync(tempPath)) {
|
||||
const result = fileList!
|
||||
.map(item => {
|
||||
if (isUrl(item)) {
|
||||
return {
|
||||
path: tempPath
|
||||
path: item
|
||||
}
|
||||
}
|
||||
if (path.isAbsolute(item)) {
|
||||
return {
|
||||
path: item
|
||||
}
|
||||
} else {
|
||||
logger.warn(`cli -> can't get file: ${tempPath}, invalid path`)
|
||||
return null
|
||||
const tempPath = path.join(cwd, item)
|
||||
if (fs.existsSync(tempPath)) {
|
||||
return {
|
||||
path: tempPath
|
||||
}
|
||||
} else {
|
||||
logger.warn(`cli -> can't get file: ${tempPath}, invalid path`)
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
}).filter(item => item !== null) as Result
|
||||
})
|
||||
.filter(item => item !== null) as Result
|
||||
return result
|
||||
}
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
export {
|
||||
getUploadFiles
|
||||
}
|
||||
export { getUploadFiles }
|
||||
|
||||
@@ -13,6 +13,7 @@ export const handleConfigWithFunction = (config: IPicGoPluginOriginConfig[]): IP
|
||||
config[i].default = config[i].default()
|
||||
}
|
||||
if (typeof config[i].choices === 'function') {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
config[i].choices = (config[i].choices as Function)()
|
||||
}
|
||||
}
|
||||
@@ -20,13 +21,17 @@ export const handleConfigWithFunction = (config: IPicGoPluginOriginConfig[]): IP
|
||||
}
|
||||
|
||||
export const completeUploaderMetaConfig = (originData: IStringKeyMap): IUploaderConfigListItem => {
|
||||
return Object.assign({
|
||||
_configName: 'Default'
|
||||
}, trimValues(originData), {
|
||||
_id: uuid(),
|
||||
_createdAt: Date.now(),
|
||||
_updatedAt: Date.now()
|
||||
})
|
||||
return Object.assign(
|
||||
{
|
||||
_configName: 'Default'
|
||||
},
|
||||
trimValues(originData),
|
||||
{
|
||||
_id: uuid(),
|
||||
_createdAt: Date.now(),
|
||||
_updatedAt: Date.now()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,7 +135,9 @@ export const deleteUploaderConfig = (type: string, id: string): IUploaderConfigI
|
||||
/**
|
||||
* upgrade old uploader config to new format
|
||||
*/
|
||||
export const upgradeUploaderConfig = (type: string): {
|
||||
export const upgradeUploaderConfig = (
|
||||
type: string
|
||||
): {
|
||||
configList: IStringKeyMap[]
|
||||
defaultId: string
|
||||
} => {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-nocheck
|
||||
import fs from 'fs-extra'
|
||||
import { NodeSSH, Config, SSHExecCommandResponse } from 'node-ssh-no-cpu-features'
|
||||
import path from 'path'
|
||||
@@ -11,22 +10,26 @@ class SSHClient {
|
||||
private static _client: NodeSSH
|
||||
private _isConnected = false
|
||||
|
||||
static get instance (): SSHClient {
|
||||
static get instance(): SSHClient {
|
||||
return this._instance || (this._instance = new this())
|
||||
}
|
||||
|
||||
static get client (): NodeSSH {
|
||||
static get client(): NodeSSH {
|
||||
return this._client || (this._client = new NodeSSH())
|
||||
}
|
||||
|
||||
private changeWinStylePathToUnix (path: string): string {
|
||||
private changeWinStylePathToUnix(path: string): string {
|
||||
return path.replace(/\\/g, '/')
|
||||
}
|
||||
|
||||
async connect (config: ISftpPlistConfig): Promise<boolean> {
|
||||
async connect(config: ISftpPlistConfig): Promise<boolean> {
|
||||
const { username, password, privateKey, passphrase } = config
|
||||
const loginInfo: Config = privateKey
|
||||
? { username, privateKeyPath: privateKey, passphrase: passphrase || undefined }
|
||||
? {
|
||||
username,
|
||||
privateKeyPath: privateKey,
|
||||
passphrase: passphrase || undefined
|
||||
}
|
||||
: { username, password }
|
||||
try {
|
||||
await SSHClient.client.connect({
|
||||
@@ -41,52 +44,64 @@ class SSHClient {
|
||||
}
|
||||
}
|
||||
|
||||
async deleteFileSFTP (config: ISftpPlistConfig, remote: string): Promise<boolean> {
|
||||
async deleteFileSFTP(config: ISftpPlistConfig, remote: string): Promise<boolean> {
|
||||
try {
|
||||
const client = new Client()
|
||||
const { username, password, privateKey, passphrase } = config
|
||||
const loginInfo: Config = privateKey
|
||||
? { username, privateKey: fs.readFileSync(privateKey), passphrase: passphrase || undefined }
|
||||
? {
|
||||
username,
|
||||
privateKey: fs.readFileSync(privateKey),
|
||||
passphrase: passphrase || undefined
|
||||
}
|
||||
: { username, password }
|
||||
remote = this.changeWinStylePathToUnix(remote)
|
||||
if (remote === '/' || remote.includes('*')) return false
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
client.on('ready', () => {
|
||||
client.sftp((err, sftp) => {
|
||||
// eslint-disable-next-line prefer-promise-reject-errors
|
||||
if (err) reject(false)
|
||||
sftp.unlink(remote, (err) => {
|
||||
// eslint-disable-next-line prefer-promise-reject-errors
|
||||
if (err) reject(false)
|
||||
client.end()
|
||||
resolve(true)
|
||||
})
|
||||
client
|
||||
.on('ready', () => {
|
||||
client.sftp(
|
||||
(
|
||||
err: any,
|
||||
sftp: {
|
||||
unlink: (arg0: string, arg1: (err: any) => void) => void
|
||||
}
|
||||
) => {
|
||||
// eslint-disable-next-line prefer-promise-reject-errors
|
||||
if (err) reject(false)
|
||||
sftp.unlink(remote, (err: any) => {
|
||||
// eslint-disable-next-line prefer-promise-reject-errors
|
||||
if (err) reject(false)
|
||||
client.end()
|
||||
resolve(true)
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
}).connect({
|
||||
host: config.host,
|
||||
port: Number(config.port) || 22,
|
||||
...loginInfo
|
||||
})
|
||||
}
|
||||
)
|
||||
return await promise
|
||||
.connect({
|
||||
host: config.host,
|
||||
port: Number(config.port) || 22,
|
||||
...loginInfo
|
||||
})
|
||||
})
|
||||
return (await promise) as boolean
|
||||
} catch (err: any) {
|
||||
console.log(err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private async exec (script: string): Promise<boolean> {
|
||||
private async exec(script: string): Promise<boolean> {
|
||||
const execResult = await SSHClient.client.execCommand(script)
|
||||
return execResult.code === 0
|
||||
}
|
||||
|
||||
async execCommand (script: string): Promise<SSHExecCommandResponse> {
|
||||
async execCommand(script: string): Promise<SSHExecCommandResponse> {
|
||||
const execResult = await SSHClient.client.execCommand(script)
|
||||
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) {
|
||||
throw new Error('SSH 未连接')
|
||||
}
|
||||
@@ -103,10 +118,14 @@ class SSHClient {
|
||||
}
|
||||
}
|
||||
|
||||
async putFile (local: string, remote: string, config: {
|
||||
fileMode?: string
|
||||
dirMode?: string
|
||||
} = {}): Promise<boolean> {
|
||||
async putFile(
|
||||
local: string,
|
||||
remote: string,
|
||||
config: {
|
||||
fileMode?: string
|
||||
dirMode?: string
|
||||
} = {}
|
||||
): Promise<boolean> {
|
||||
if (!this._isConnected) {
|
||||
throw new Error('SSH 未连接')
|
||||
}
|
||||
@@ -126,9 +145,12 @@ class SSHClient {
|
||||
}
|
||||
}
|
||||
|
||||
async mkdir (dirPath: string, config: {
|
||||
dirMode?: string
|
||||
} = {}): Promise<boolean> {
|
||||
async mkdir(
|
||||
dirPath: string,
|
||||
config: {
|
||||
dirMode?: string
|
||||
} = {}
|
||||
): Promise<boolean> {
|
||||
if (!this._isConnected) {
|
||||
throw new Error('SSH 未连接')
|
||||
}
|
||||
@@ -158,11 +180,11 @@ class SSHClient {
|
||||
}
|
||||
}
|
||||
|
||||
get isConnected (): boolean {
|
||||
get isConnected(): boolean {
|
||||
return SSHClient.client.isConnected()
|
||||
}
|
||||
|
||||
close (): void {
|
||||
close(): void {
|
||||
SSHClient.client.dispose()
|
||||
this._isConnected = false
|
||||
}
|
||||
|
||||
@@ -15,32 +15,35 @@ const STORE_PATH = app.getPath('userData')
|
||||
const readFileAsBase64 = (filePath: string) => fs.readFileSync(filePath, { encoding: 'base64' })
|
||||
|
||||
const isHttpResSuccess = (res: any) => res.status >= 200 && res.status < 300
|
||||
const uploadOrUpdateMsg = (fileName: string, isUpdate: boolean = true) => isUpdate ? `update ${fileName} from PicList` : `upload ${fileName} from PicList`
|
||||
const uploadOrUpdateMsg = (fileName: string, isUpdate: boolean = true) =>
|
||||
isUpdate ? `update ${fileName} from PicList` : `upload ${fileName} from PicList`
|
||||
|
||||
const getSyncConfig = () => {
|
||||
return db.get(configPaths.settings.sync) || {
|
||||
type: 'github',
|
||||
username: '',
|
||||
repo: '',
|
||||
branch: '',
|
||||
token: '',
|
||||
proxy: ''
|
||||
}
|
||||
return (
|
||||
db.get(configPaths.settings.sync) || {
|
||||
type: 'github',
|
||||
username: '',
|
||||
repo: '',
|
||||
branch: '',
|
||||
token: '',
|
||||
proxy: ''
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const getProxyagent = (proxy: string | undefined) => {
|
||||
return proxy
|
||||
? new HttpsProxyAgent({
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 1000,
|
||||
rejectUnauthorized: false,
|
||||
proxy: proxy.replace('127.0.0.1', 'localhost'),
|
||||
scheduling: 'lifo'
|
||||
})
|
||||
keepAlive: true,
|
||||
keepAliveMsecs: 1000,
|
||||
rejectUnauthorized: false,
|
||||
proxy: proxy.replace('127.0.0.1', 'localhost'),
|
||||
scheduling: 'lifo'
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
|
||||
function getOctokit (syncConfig: ISyncConfig) {
|
||||
function getOctokit(syncConfig: ISyncConfig) {
|
||||
const { token, proxy } = syncConfig
|
||||
return new Octokit({
|
||||
auth: token,
|
||||
@@ -50,17 +53,11 @@ function getOctokit (syncConfig: ISyncConfig) {
|
||||
})
|
||||
}
|
||||
|
||||
const isSyncConfigValidate = ({
|
||||
type,
|
||||
username,
|
||||
repo,
|
||||
branch,
|
||||
token
|
||||
}: ISyncConfig) => {
|
||||
const isSyncConfigValidate = ({ type, username, repo, branch, token }: ISyncConfig) => {
|
||||
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)
|
||||
if (!fs.existsSync(localFilePath)) {
|
||||
return false
|
||||
@@ -109,7 +106,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)
|
||||
if (!fs.existsSync(localFilePath)) {
|
||||
return false
|
||||
@@ -179,12 +176,16 @@ async function updateLocalToRemote (syncConfig: ISyncConfig, fileName: string) {
|
||||
}
|
||||
const data = shaRes.data as any
|
||||
const sha = data.sha
|
||||
const res = await axios.put(apiUrl, {
|
||||
...defaultConfig,
|
||||
sha
|
||||
}, {
|
||||
headers
|
||||
})
|
||||
const res = await axios.put(
|
||||
apiUrl,
|
||||
{
|
||||
...defaultConfig,
|
||||
sha
|
||||
},
|
||||
{
|
||||
headers
|
||||
}
|
||||
)
|
||||
return isHttpResSuccess(res)
|
||||
}
|
||||
default:
|
||||
@@ -192,7 +193,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()
|
||||
if (!isSyncConfigValidate(syncConfig)) {
|
||||
logger.error('sync config is invalid')
|
||||
@@ -217,16 +218,19 @@ async function uploadFile (fileName: string[]): Promise<number> {
|
||||
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)
|
||||
if (isHttpResSuccess(res)) {
|
||||
await fs.writeFile(localFilePath, isWriteJson ? JSON.stringify(res.data, null, 2) : Buffer.from(res.data.content, 'base64'))
|
||||
await fs.writeFile(
|
||||
localFilePath,
|
||||
isWriteJson ? JSON.stringify(res.data, null, 2) : Buffer.from(res.data.content, 'base64')
|
||||
)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
async function downloadRemoteToLocal (syncConfig: ISyncConfig, fileName: string) {
|
||||
async function downloadRemoteToLocal(syncConfig: ISyncConfig, fileName: string) {
|
||||
const localFilePath = path.join(STORE_PATH, fileName)
|
||||
const { username, repo, branch, token, proxy, type } = syncConfig
|
||||
try {
|
||||
@@ -251,9 +255,14 @@ async function downloadRemoteToLocal (syncConfig: ISyncConfig, fileName: string)
|
||||
if (res.status === 200) {
|
||||
const data = res.data as any
|
||||
const downloadUrl = data.download_url
|
||||
return downloadAndWriteFile(downloadUrl, localFilePath, {
|
||||
httpsAgent: getProxyagent(proxy)
|
||||
}, true)
|
||||
return downloadAndWriteFile(
|
||||
downloadUrl,
|
||||
localFilePath,
|
||||
{
|
||||
httpsAgent: getProxyagent(proxy)
|
||||
},
|
||||
true
|
||||
)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -278,7 +287,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()
|
||||
if (!isSyncConfigValidate(syncConfig)) {
|
||||
logger.error('sync config is invalid')
|
||||
@@ -294,7 +303,4 @@ async function downloadFile (fileName: string[]): Promise<number> {
|
||||
return (await Promise.all(fileName.map(downloadFunc))).reduce((a, b) => a + b, 0)
|
||||
}
|
||||
|
||||
export {
|
||||
uploadFile,
|
||||
downloadFile
|
||||
}
|
||||
export { uploadFile, downloadFile }
|
||||
|
||||
@@ -7,7 +7,7 @@ import windowManager from 'apis/app/window/windowManager'
|
||||
import { IWindowList } from '#/types/enum'
|
||||
import { configPaths } from '#/utils/configPaths'
|
||||
|
||||
export function openMiniWindow (hideSettingWindow:boolean = true) {
|
||||
export function openMiniWindow(hideSettingWindow: boolean = true) {
|
||||
const miniWindow = windowManager.get(IWindowList.MINI_WINDOW)!
|
||||
miniWindow.removeAllListeners()
|
||||
if (db.get(configPaths.settings.miniWindowOntop)) {
|
||||
|
||||
Reference in New Issue
Block a user