Skip to content

Commit

Permalink
Merge pull request #329 from terwer/dev
Browse files Browse the repository at this point in the history
new version of picgo
  • Loading branch information
terwer committed Mar 27, 2024
2 parents 3ff9f5e + ab9f909 commit bf5d05a
Show file tree
Hide file tree
Showing 122 changed files with 8,691 additions and 862 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -4,7 +4,7 @@

![](./preview.png)

Your favorite PicGo image bed and PicGo plugins are still available in siyuan-notes, wuhu~
Your favorite PicGo image bed is still available in siyuan-notes, wuhu~

> Important Note:
>
Expand Down
2 changes: 1 addition & 1 deletion README_zh_CN.md
Expand Up @@ -4,7 +4,7 @@

![](./preview.png)

您喜爱的 PicGo 图床与 PicGo 插件,在思源笔记依然可用,没想到吧~
您喜爱的 PicGo 图床在思源笔记依然可用,没想到吧~

> 重要提示:
>
Expand Down
Binary file modified icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icon.psd
Binary file not shown.
6 changes: 5 additions & 1 deletion libs/Universal-PicGo-Core/custom.d.ts
@@ -1,4 +1,8 @@
declare module '*.json' {
const value: { [key: string]: any }
export default value
}
}

declare module "ali-oss"
declare module "arraybuffer-to-buffer"
declare module "upyun"
3 changes: 3 additions & 0 deletions libs/Universal-PicGo-Core/package.json
Expand Up @@ -27,13 +27,16 @@
"devDependencies": {
"@terwer/eslint-config-custom": "^1.3.6",
"@terwer/vite-config-custom": "^0.7.6",
"@types/mime-types": "^2.1.4",
"vite-plugin-node-polyfills": "^0.21.0"
},
"dependencies": {
"@picgo/i18n": "^1.0.0",
"ali-oss": "^6.20.0",
"axios": "^1.6.8",
"dayjs": "^1.11.10",
"js-yaml": "^4.1.0",
"mime-types": "^2.1.35",
"queue": "^7.0.0",
"universal-picgo-store": "workspace:*",
"zhi-lib-base": "^0.8.0"
Expand Down
122 changes: 122 additions & 0 deletions libs/Universal-PicGo-Core/src/core/ExternalPicgo.ts
@@ -0,0 +1,122 @@
/*
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* Copyright (C) 2022-2024 Terwer, Inc. <https://terwer.space/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/

import { ILogger, simpleLogger } from "zhi-lib-base"
import ExternalPicgoConfigDb from "../db/externalPicGo"
import { IImgInfo, IPicGo } from "../types"
import { PicgoTypeEnum } from "../utils/enums"
import { browserPathJoin } from "../utils/browserUtils"
import { isFileOrBlob } from "../utils/common"

/**
*外部的PicGO 上传 Api
*
* @since 0.6.0
* @version 1.6.0
* @author terwer
*/
class ExternalPicgo {
private logger: ILogger
private requestUrl = "http://127.0.0.1:36677"
private readonly endpointUrl = "/upload"
public db: ExternalPicgoConfigDb

constructor(ctx: IPicGo, isDev?: boolean) {
this.logger = simpleLogger("external-picgo", "external-picgo", isDev)
this.db = new ExternalPicgoConfigDb(ctx)
}

/**
* 上传图片到PicGO
*
* @param input 路径数组,可为空,为空上传剪贴板
*/
public async upload(input?: any[]): Promise<IImgInfo[] | Error> {
const useBundledPicgo = this.db.get("useBundledPicgo")
const picgoType = this.db.get("picgoType")
if (useBundledPicgo) {
throw new Error("bundled picgo cannot use extenal picgo api")
}
if (picgoType !== PicgoTypeEnum.App) {
throw new Error(`picgoType ${picgoType} is not supported via external picgo api`)
}

// check blob
let hasBlob = false
if (input) {
for (const inputItem of input) {
if (isFileOrBlob(inputItem) || typeof inputItem !== "string") {
hasBlob = true
break
}
}
}
if (hasBlob) {
throw new Error("blob is not supported via external picgo api")
}

this.requestUrl = this.db.get("extPicgoApiUrl") ?? this.requestUrl
let ret: IImgInfo[] = []

const fetchOptions = {
method: "POST",
}

let data
// 传递了路径,上传具体图片,否则上传剪贴板
if (input) {
data = { list: input }
}

// 数据不为空才传递
if (data) {
Object.assign(fetchOptions, {
body: JSON.stringify(data),
})
}

Object.assign(fetchOptions, {
headers: {
"Content-Type": "application/json",
"User-Agent": "Terwer/0.1.0",
},
})

// 发送请求
const apiUrl = browserPathJoin(this.requestUrl, this.endpointUrl)
this.logger.debug("调用HTTP请求上传图片到PicGO,apiUrl=>", apiUrl)
this.logger.debug("调用HTTP请求上传图片到PicGO,fetchOps=>", fetchOptions)

// 使用兼容的fetch调用并返回统一的JSON数据
const response = await fetch(apiUrl, fetchOptions)
const resJson = await response.json()
this.logger.debug("调用HTTP请求上传图片到PicGO,resJson=>", resJson)

if (resJson.success) {
const rtnArray: IImgInfo[] = []
if (resJson.result && resJson.result.length > 0) {
resJson.result.forEach((img: string) => {
const rtnItem = {
fileName: img.substring(img.lastIndexOf("/") + 1),
imgUrl: img,
}
rtnArray.push(rtnItem)
})
}

ret = rtnArray
} else {
throw new Error("调用HTTP上传到PicGO失败,请检查配置=>" + resJson.message)
}

return Promise.resolve(ret)
}
}

export { ExternalPicgo }
6 changes: 2 additions & 4 deletions libs/Universal-PicGo-Core/src/core/Lifecycle.ts
Expand Up @@ -12,7 +12,6 @@ import { ILifecyclePlugins, IPicGo, IPlugin, Undefinable } from "../types"
import { ILogger } from "zhi-lib-base"
import { createContext } from "../utils/createContext"
import { IBuildInEvent } from "../utils/enums"
import { handleUrlEncode } from "../utils/common"

export class Lifecycle extends EventEmitter {
private readonly ctx: IPicGo
Expand Down Expand Up @@ -114,11 +113,9 @@ export class Lifecycle extends EventEmitter {
await this.handlePlugins(ctx.helper.afterUploadPlugins, ctx)
let msg = ""
const length = ctx.output.length
// notice, now picgo builtin uploader will encodeOutputURL by default
const isEncodeOutputURL = ctx.getConfig<Undefinable<boolean>>("settings.encodeOutputURL") === true
for (let i = 0; i < length; i++) {
if (typeof ctx.output[i].imgUrl !== "undefined") {
msg += isEncodeOutputURL ? handleUrlEncode(ctx.output[i].imgUrl!) : ctx.output[i].imgUrl!
msg += ctx.output[i].imgUrl!
if (i !== length - 1) {
msg += "\n"
}
Expand All @@ -129,6 +126,7 @@ export class Lifecycle extends EventEmitter {
ctx.emit(IBuildInEvent.FINISHED, ctx)
if (msg === "") {
ctx.log.warn("[after-upload] image upload occured an error, please read log for details")
throw new Error("image upload occured an error, please read log for details")
} else {
ctx.log.info(`[after-upload] upload finishied => \n${msg}`)
}
Expand Down
83 changes: 47 additions & 36 deletions libs/Universal-PicGo-Core/src/core/UniversalPicGo.ts
Expand Up @@ -17,7 +17,6 @@ import {
IPicGo,
IPicGoPlugin,
IPicGoPluginInterface,
IPicGoRequest,
IPluginLoader,
IStringKeyMap,
} from "../types"
Expand All @@ -32,7 +31,7 @@ import getClipboardImage from "../utils/getClipboardImage"
import { IBuildInEvent, IBusEvent } from "../utils/enums"
import ConfigDb from "../db/config"
import { hasNodeEnv, win } from "universal-picgo-store"
import { ensureFileSync, pathExistsSync } from "../utils/nodeUtils"
import { ensureFileSync, ensureFolderSync, pathExistsSync } from "../utils/nodeUtils"
import { I18nManager } from "../i18n"
import { browserPathJoin, getBrowserDirectoryPath } from "../utils/browserUtils"
import { isConfigKeyInBlackList, isInputConfigValid } from "../utils/common"
Expand All @@ -52,9 +51,9 @@ class UniversalPicGo extends EventEmitter implements IPicGo {
private _pluginLoader!: PluginLoader
configPath: string
baseDir!: string
pluginBaseDir!: string
helper!: IHelper
log: ILogger
// cmd: Commander
output: IImgInfo[]
input: any[]
pluginHandler: PluginHandler
Expand All @@ -63,8 +62,6 @@ class UniversalPicGo extends EventEmitter implements IPicGo {
VERSION: string = process.env.PICGO_VERSION ?? "unknown"
private readonly isDev: boolean

// GUI_VERSION?: string

get pluginLoader(): IPluginLoader {
return this._pluginLoader
}
Expand All @@ -77,11 +74,12 @@ class UniversalPicGo extends EventEmitter implements IPicGo {
return this.requestWrapper.PicGoRequest.bind(this.requestWrapper)
}

constructor(configPath = "", isDev?: boolean) {
constructor(configPath?: string, pluginBaseDir?: string, isDev?: boolean) {
super()
this.isDev = isDev ?? false
this.log = this.getLogger()
this.configPath = configPath
this.configPath = configPath ?? ""
this.pluginBaseDir = pluginBaseDir ?? ""
this.output = []
this.input = []
this.helper = {
Expand All @@ -92,10 +90,9 @@ class UniversalPicGo extends EventEmitter implements IPicGo {
afterUploadPlugins: new LifecyclePlugins("afterUploadPlugins"),
}
this.initConfigPath()
// this.cmd = new Commander(this)
this.initConfig()
this.pluginHandler = new PluginHandler(this)
this.requestWrapper = new PicGoRequestWrapper(this)
this.initConfig()
this.init()

this.log.info("UniversalPicGo inited")
Expand All @@ -116,18 +113,11 @@ class UniversalPicGo extends EventEmitter implements IPicGo {
}
}

// registerCommands(): void {
// if (this.configPath !== "") {
// this.cmd.init()
// this.cmd.loadCommands()
// }
// }

getConfig<T>(name?: string): T {
getConfig<T>(name?: string, defaultValue?: any): T {
if (!name) {
return this._config as unknown as T
} else {
return _.get(this._config, name)
return _.get(this._config, name, defaultValue)
}
}

Expand Down Expand Up @@ -227,35 +217,56 @@ class UniversalPicGo extends EventEmitter implements IPicGo {

// ===================================================================================================================

private initConfigPath(): void {
this.log.debug("win =>", win)
this.log.info(`hasNodeEnv => ${hasNodeEnv}`)
private getDefautBaseDir(): string {
if (hasNodeEnv) {
const os = win.require("os")
const fs = win.fs
const path = win.require("path")
const { homedir } = os
if (this.configPath === "") {
this.configPath = homedir() + "/.universal-picgo/config.json"
}
if (path.extname(this.configPath).toUpperCase() !== ".JSON") {
this.configPath = ""
throw Error("The configuration file only supports JSON format.")
}
this.baseDir = path.dirname(this.configPath)
const exist = pathExistsSync(fs, path, this.configPath)
if (!exist) {
ensureFileSync(fs, path, `${this.configPath}`)
const dir = path.join(homedir(), ".universal-picgo")
ensureFolderSync(fs, dir)
return dir
} else {
return "universal-picgo"
}
}

private initConfigPath(): void {
if (this.configPath === "") {
this.baseDir = this.getDefautBaseDir()
if (hasNodeEnv) {
const path = win.require("path")
this.configPath = path.join(this.baseDir, "picgo.cfg.json")
} else {
this.configPath = browserPathJoin(this.baseDir, "picgo.cfg.json")
}
} else {
if (this.configPath === "") {
this.baseDir = "universal-picgo"
this.configPath = browserPathJoin(this.baseDir, "config.json")
if (hasNodeEnv) {
const fs = win.fs
const path = win.require("path")

if (path.extname(this.configPath).toUpperCase() !== ".JSON") {
this.configPath = ""
throw Error("The configuration file only supports JSON format.")
}
this.baseDir = path.dirname(this.configPath)
const exist = pathExistsSync(fs, path, this.configPath)
if (!exist) {
ensureFileSync(fs, path, `${this.configPath}`)
}
} else {
// 模拟 path.dirname 的功能,获取路径的目录部分赋值给 baseDir
this.baseDir = getBrowserDirectoryPath(this.configPath)
}
}

if (this.pluginBaseDir === "") {
this.pluginBaseDir = this.getDefautBaseDir()
}

this.log.debug("win =>", win)
this.log.info(`hasNodeEnv => ${hasNodeEnv}`)
this.log.info(`this.baseDir => ${this.baseDir}`)
this.log.info(`this.pluginBaseDir => ${this.pluginBaseDir}`)
}

private initConfig(): void {
Expand Down

0 comments on commit bf5d05a

Please sign in to comment.