From d4a22f9e6311b519c41752a4e05b1b51a3dd1c8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=8C=E8=90=8C=E5=93=92=E8=B5=AB=E8=90=9D?= Date: Tue, 11 Jul 2023 20:07:33 -0700 Subject: [PATCH] :sparkles: Feature: add custom short url server #69 ISSUES CLOSED: #69 --- package.json | 2 +- public/i18n/en.yml | 3 + public/i18n/zh-CN.yml | 3 + public/i18n/zh-TW.yml | 3 + src/main/events/ipcList.ts | 4 +- src/main/utils/common.ts | 46 +++++++++++++++ src/main/utils/pasteTemplate.ts | 2 +- src/renderer/apis/allApi.ts | 4 +- src/renderer/apis/local.ts | 23 ++++++++ src/renderer/manage/pages/bucketPage.vue | 1 - src/renderer/pages/Gallery.vue | 4 +- src/renderer/pages/PicGoSetting.vue | 71 ++++++++++++++++++++++++ src/universal/types/i18n.d.ts | 3 + src/universal/types/view.d.ts | 3 + src/universal/utils/common.ts | 25 --------- yarn.lock | 8 +-- 16 files changed, 167 insertions(+), 38 deletions(-) create mode 100644 src/renderer/apis/local.ts diff --git a/package.json b/package.json index 082c8b8..0ac62f0 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "mime-types": "^2.1.35", "mitt": "^3.0.0", "nodejs-file-downloader": "^4.12.1", - "piclist": "^0.7.3", + "piclist": "^0.7.4", "pinia": "^2.1.4", "pinia-plugin-persistedstate": "^3.1.0", "qiniu": "^7.8.0", diff --git a/public/i18n/en.yml b/public/i18n/en.yml index c4e1d76..6ffbf52 100644 --- a/public/i18n/en.yml +++ b/public/i18n/en.yml @@ -227,6 +227,9 @@ SETTINGS_ISHIDEDOCK_TIPS: Not support hide dock and tray at the same time SETTINGS_ENCODE_OUTPUT_URL: Encode Output(or Copyed) URL SETTINGS_WATCH_CLIPBOARD: Watch clipboard when software start SETTINGS_SHORT_URL: Use short url +SETTINGS_SHORT_URL_SERVER: Short url server +SETTINGS_SHORT_URL_YOURLS_DOMAIN: YOURLS domain +SETTINGS_SHORT_URL_YOURLS_SIGNATURE: YOURLS signature SETTINGS_DELETE_LOCAL_FILE_AFTER_UPLOAD: Delete local file after upload SETTINGS_SYNC_CONFIG: Settings Sync Configuration SETTINGS_SYNC_CONFIG_TITLE: Sync Settings diff --git a/public/i18n/zh-CN.yml b/public/i18n/zh-CN.yml index 3c50ac7..d32fe65 100644 --- a/public/i18n/zh-CN.yml +++ b/public/i18n/zh-CN.yml @@ -230,6 +230,9 @@ SETTINGS_ISHIDEDOCK_TIPS: 不支持同时隐藏dock和托盘 SETTINGS_ENCODE_OUTPUT_URL: 输出(复制) URL 时进行转义 SETTINGS_WATCH_CLIPBOARD: 软件启动时自动监听剪贴板上传 SETTINGS_SHORT_URL: 使用短链接 +SETTINGS_SHORT_URL_SERVER: 短链接服务 +SETTINGS_SHORT_URL_YOURLS_DOMAIN: YOURLS域名 +SETTINGS_SHORT_URL_YOURLS_SIGNATURE: YOURLS signature SETTINGS_DELETE_LOCAL_FILE_AFTER_UPLOAD: 上传后删除本地文件 SETTINGS_SYNC_CONFIG: 设置配置同步 SETTINGS_SYNC_CONFIG_TITLE: 同步设置 diff --git a/public/i18n/zh-TW.yml b/public/i18n/zh-TW.yml index 8000323..046a63e 100644 --- a/public/i18n/zh-TW.yml +++ b/public/i18n/zh-TW.yml @@ -228,6 +228,9 @@ SETTINGS_ISHIDEDOCK_TIPS: 不支持同時隱藏dock和托盘 SETTINGS_ENCODE_OUTPUT_URL: 輸出(複製) URL 時進行轉義 SETTINGS_WATCH_CLIPBOARD: 軟體啟動時自動監聽剪貼簿上傳 SETTINGS_SHORT_URL: 使用短網址 +SETTINGS_SHORT_URL_SERVER: 短網址服務 +SETTINGS_SHORT_URL_YOURLS_DOMAIN: YOURLS域名 +SETTINGS_SHORT_URL_YOURLS_SIGNATURE: YOURLS signature SETTINGS_DELETE_LOCAL_FILE_AFTER_UPLOAD: 上傳後刪除本地檔案 SETTINGS_SYNC_CONFIG: 設置同步配置 SETTINGS_SYNC_CONFIG_TITLE: 同步設置 diff --git a/src/main/events/ipcList.ts b/src/main/events/ipcList.ts index 89bdb73..3cf1b7d 100644 --- a/src/main/events/ipcList.ts +++ b/src/main/events/ipcList.ts @@ -39,11 +39,10 @@ import { uploadChoosedFiles } from '~/main/apis/app/uploader/apis' import picgoCoreIPC from './picgoCoreIPC' -import { handleCopyUrl } from '~/main/utils/common' +import { handleCopyUrl, generateShortUrl } from '~/main/utils/common' import { buildMainPageMenu, buildMiniPageMenu, buildPluginPageMenu, buildPicBedListMenu } from './remotes/menu' import path from 'path' import { T } from '~/main/i18n' -import { generateShortUrl } from '~/universal/utils/common' import { uploadFile, downloadFile } from '../utils/syncSettings' const STORE_PATH = app.getPath('userData') @@ -76,7 +75,6 @@ export default { }) ipcMain.on('uploadClipboardFilesFromUploadPage', () => { - console.log('handle') uploadClipboardFiles() }) diff --git a/src/main/utils/common.ts b/src/main/utils/common.ts index 733677c..99c1e06 100644 --- a/src/main/utils/common.ts +++ b/src/main/utils/common.ts @@ -2,6 +2,10 @@ import fs from 'fs-extra' import db from '~/main/apis/core/datastore' import { clipboard, Notification, dialog } from 'electron' import { handleUrlEncode } from '~/universal/utils/common' +import axios from 'axios' +import FormData from 'form-data' +import { C1 } from '#/utils/static' +import logger from '../apis/core/picgo/logger' export const handleCopyUrl = (str: string): void => { if (db.get('settings.autoCopy') !== false) { @@ -96,3 +100,45 @@ export const getClipboardFilePath = (): string => { } export const handleUrlEncodeWithSetting = (url: string) => db.get('settings.encodeOutputURL') ? handleUrlEncode(url) : url + +const c1nApi = 'https://c1n.cn/link/short' + +export const generateShortUrl = async (url: string) => { + const server = db.get('settings.shortUrlServer') || 'c1n' + if (server === 'c1n') { + const form = new FormData() + form.append('url', url) + const C = Buffer.from(C1, 'base64').toString() + try { + const res = await axios.post(c1nApi, form, { + headers: { + token: C + } + }) + if (res.status >= 200 && res.status < 300 && res.data?.code === 0) { + return res.data.data + } + } catch (e: any) { + console.log(e) + } + } else if (server === 'yourls') { + const domain = db.get('settings.yourlsDomain') || '' + const signature = db.get('settings.yourlsSignature') || '' + if (domain && signature) { + try { + const res = await axios.get(`${domain}/yourls-api.php?signature=${signature}&action=shorturl&format=json&url=${url}`) + if (res.data.shorturl) { + return res.data.shorturl + } + } catch (e: any) { + if (e.response.data.message.indexOf('already exists in database') !== -1) { + return e.response.data.shorturl + } + console.log(e) + } + } else { + logger.warn('Yourls server or signature is not set') + } + } + return url +} diff --git a/src/main/utils/pasteTemplate.ts b/src/main/utils/pasteTemplate.ts index bffae27..18e21a1 100644 --- a/src/main/utils/pasteTemplate.ts +++ b/src/main/utils/pasteTemplate.ts @@ -1,5 +1,5 @@ import { IPasteStyle } from '#/types/enum' -import { generateShortUrl } from '#/utils/common' +import { generateShortUrl } from '~/main/utils/common' import db from '~/main/apis/core/datastore' import { handleUrlEncodeWithSetting } from './common' diff --git a/src/renderer/apis/allApi.ts b/src/renderer/apis/allApi.ts index 79234f1..92c6bf7 100644 --- a/src/renderer/apis/allApi.ts +++ b/src/renderer/apis/allApi.ts @@ -7,6 +7,7 @@ import GithubApi from './github' import UpyunApi from './upyun' import AwsS3Api from './awss3' import WebdavApi from './webdav' +import LocalApi from './local' const apiMap: IStringKeyMap = { smms: SmmsApi, @@ -17,7 +18,8 @@ const apiMap: IStringKeyMap = { github: GithubApi, upyun: UpyunApi, 'aws-s3': AwsS3Api, - webdavplist: WebdavApi + webdavplist: WebdavApi, + local: LocalApi } export default class ALLApi { diff --git a/src/renderer/apis/local.ts b/src/renderer/apis/local.ts new file mode 100644 index 0000000..3dcdb27 --- /dev/null +++ b/src/renderer/apis/local.ts @@ -0,0 +1,23 @@ +import fs from 'fs-extra' + +interface IConfigMap { + hash: string +} + +export default class LocalApi { + static async delete (configMap: IConfigMap): Promise { + const { hash } = configMap + if (!hash) { + console.error('SmmsApi.delete: invalid params') + return false + } + + try { + await fs.remove(hash) + return true + } catch (error) { + console.error(error) + return false + } + } +} diff --git a/src/renderer/manage/pages/bucketPage.vue b/src/renderer/manage/pages/bucketPage.vue index c50e8f8..7e08629 100644 --- a/src/renderer/manage/pages/bucketPage.vue +++ b/src/renderer/manage/pages/bucketPage.vue @@ -3663,7 +3663,6 @@ const columns: Column[] = [ ] onBeforeMount(async () => { - console.log('onBeforeMount') await manageStore.refreshConfig() showLoadingPage.value = true await initCustomUrlList() diff --git a/src/renderer/pages/Gallery.vue b/src/renderer/pages/Gallery.vue index 519fb30..f4af9d8 100644 --- a/src/renderer/pages/Gallery.vue +++ b/src/renderer/pages/Gallery.vue @@ -661,7 +661,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'] + const picBedsCanbeDeleted = ['smms', 'github', 'imgur', 'tcyun', 'aliyun', 'qiniu', 'upyun', 'aws-s3', 'webdavplist', 'local'] if (await getConfig('settings.deleteCloudFile')) { if (item.type !== undefined && picBedsCanbeDeleted.includes(item.type)) { const result = await ALLApi.delete(item) @@ -771,7 +771,7 @@ function multiRemove () { const files: IResult[] = [] const imageIDList = Object.keys(choosedList) const isDeleteCloudFile = await getConfig('settings.deleteCloudFile') - const picBedsCanbeDeleted = ['smms', 'github', 'imgur', 'tcyun', 'aliyun', 'qiniu', 'upyun', 'aws-s3', 'webdavplist'] + const picBedsCanbeDeleted = ['smms', 'github', 'imgur', 'tcyun', 'aliyun', 'qiniu', 'upyun', 'aws-s3', 'webdavplist', 'local'] if (isDeleteCloudFile) { for (let i = 0; i < imageIDList.length; i++) { const key = imageIDList[i] diff --git a/src/renderer/pages/PicGoSetting.vue b/src/renderer/pages/PicGoSetting.vue index 7d23a4f..2e56357 100644 --- a/src/renderer/pages/PicGoSetting.vue +++ b/src/renderer/pages/PicGoSetting.vue @@ -373,6 +373,49 @@ @change="handleUseShortUrl" /> + + + + + + + + + + + @@ -1376,6 +1419,16 @@ import { buildInRenameFormatTable } from '../manage/utils/common' const imageProcessDialogVisible = ref(false) const activeName = ref<'system' | 'syncAndConfigure' | 'upload' | 'advanced' | 'upadte'>('system') +const shortUrlServerList = [{ + label: 'c1n', + value: 'c1n' +}, +{ + label: 'yourls', + value: 'yourls' +} +] + const waterMarkPositionMap = new Map([ ['north', $T('UPLOAD_PAGE_IMAGE_PROCESS_POSITION_TOP')], ['northeast', $T('UPLOAD_PAGE_IMAGE_PROCESS_POSITION_TOP_RIGHT')], @@ -1489,6 +1542,9 @@ const form = reactive({ encodeOutputURL: false, isAutoListenClipboard: false, useShortUrl: false, + shortUrlServer: 'c1n', + yourlsDomain: '', + yourlsSignature: '', deleteLocalFile: false }) @@ -1638,6 +1694,9 @@ async function initData () { form.customMiniIcon = settings.customMiniIcon || '' form.isHideDock = settings.isHideDock || false form.useShortUrl = settings.useShortUrl || false + form.shortUrlServer = settings.shortUrlServer || 'c1n' + form.yourlsDomain = settings.yourlsDomain || '' + form.yourlsSignature = settings.yourlsSignature || '' form.deleteLocalFile = settings.deleteLocalFile || false currentLanguage.value = settings.language ?? 'zh-CN' currentStartMode.value = settings.startMode || 'quiet' @@ -1955,6 +2014,18 @@ function handleUseShortUrl (val: ICheckBoxValueType) { } } +function handleShortUrlServerChange (val: string) { + saveConfig('settings.shortUrlServer', val) +} + +function handleYourlsDomainChange (val: string) { + saveConfig('settings.yourlsDomain', val) +} + +function handleYourlsSignatureChange (val: string) { + saveConfig('settings.yourlsSignature', val) +} + function confirmLogLevelSetting () { if (form.logLevel.length === 0) { return $message.error($T('TIPS_PLEASE_CHOOSE_LOG_LEVEL')) diff --git a/src/universal/types/i18n.d.ts b/src/universal/types/i18n.d.ts index 7810638..78f3ad7 100644 --- a/src/universal/types/i18n.d.ts +++ b/src/universal/types/i18n.d.ts @@ -223,6 +223,9 @@ interface ILocales { SETTINGS_ENCODE_OUTPUT_URL: string SETTINGS_WATCH_CLIPBOARD: string SETTINGS_SHORT_URL: string + SETTINGS_SHORT_URL_SERVER: string + SETTINGS_SHORT_URL_YOURLS_DOMAIN: string + SETTINGS_SHORT_URL_YOURLS_SIGNATURE: string SETTINGS_DELETE_LOCAL_FILE_AFTER_UPLOAD: string SETTINGS_SYNC_CONFIG: string SETTINGS_SYNC_CONFIG_TITLE: string diff --git a/src/universal/types/view.d.ts b/src/universal/types/view.d.ts index 574ec38..987bed6 100644 --- a/src/universal/types/view.d.ts +++ b/src/universal/types/view.d.ts @@ -20,6 +20,9 @@ interface ISettingForm { encodeOutputURL: boolean, isAutoListenClipboard: boolean, useShortUrl: boolean, + shortUrlServer: string, + yourlsDomain: string, + yourlsSignature: string, deleteLocalFile: boolean } diff --git a/src/universal/utils/common.ts b/src/universal/utils/common.ts index 33e9769..9875843 100644 --- a/src/universal/utils/common.ts +++ b/src/universal/utils/common.ts @@ -1,7 +1,3 @@ -import axios from 'axios' -import FormData from 'form-data' -import { C1 } from './static' - export const isUrl = (url: string): boolean => { try { return Boolean(new URL(url)) @@ -48,24 +44,3 @@ export const isDev = process.env.NODE_ENV === 'development' export const trimValues = (obj: T): {[K in keyof T]: T[K] extends string ? string : T[K]} => { return Object.fromEntries(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]} } - -const c1nApi = 'https://c1n.cn/link/short' - -export const generateShortUrl = async (url: string) => { - const form = new FormData() - form.append('url', url) - const C = Buffer.from(C1, 'base64').toString() - try { - const res = await axios.post(c1nApi, form, { - headers: { - token: C - } - }) - if (res.status >= 200 && res.status < 300 && res.data?.code === 0) { - return res.data.data - } - } catch (e: any) { - console.log(e) - } - return url -} diff --git a/yarn.lock b/yarn.lock index f3329c2..a2af325 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11054,10 +11054,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.7.3: - version "0.7.3" - resolved "https://registry.npmjs.org/piclist/-/piclist-0.7.3.tgz#41435eb56157890e6720804faf1afcf098d41ef6" - integrity sha512-0mvD3QJm2VKuJfRbg/FBm5osh0SnHwiKSMZ2XphjfAyO4T1So9Y5XnuiGDLOYXiAMWnwbBMrixjiVahcsgGknA== +piclist@^0.7.4: + version "0.7.4" + resolved "https://registry.npmjs.org/piclist/-/piclist-0.7.4.tgz#125c9f337e2d7375ae0c5c17fafaf924134fd65f" + integrity sha512-PxE6S93uWP7sQNyMi6R7ZEs57oOXgm/nD14Moi0k0dbAlvtm1kWdrc4CboW/6e7hPVgeqT7pGi0+y0SF8iTxOA== dependencies: "@picgo/i18n" "^1.0.0" "@picgo/store" "^2.0.4"