Skip to content

Commit

Permalink
feat: 支持 Halo - 支持上传图片
Browse files Browse the repository at this point in the history
  • Loading branch information
terwer committed Sep 21, 2023
1 parent 5df6ed9 commit 3e13fb5
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 2 deletions.
20 changes: 20 additions & 0 deletions src/adaptors/api/base/baseBlogApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { PublisherAppInstance } from "~/src/publisherAppInstance.ts"
import { createAppLogger, ILogger } from "~/src/utils/appLogger.ts"
import { useProxy } from "~/src/composables/useProxy.ts"
import { BaseExtendApi } from "~/src/adaptors/base/baseExtendApi.ts"
import { JsonUtil } from "zhi-common"

/**
* API授权统一封装基类
Expand All @@ -37,6 +38,7 @@ import { BaseExtendApi } from "~/src/adaptors/base/baseExtendApi.ts"
* @since 0.9.0
*/
export class BaseBlogApi extends BlogApi {
protected appInstance: PublisherAppInstance
protected logger: ILogger
protected cfg: BlogConfig
public readonly proxyFetch: any
Expand All @@ -51,6 +53,7 @@ export class BaseBlogApi extends BlogApi {
constructor(appInstance: PublisherAppInstance, cfg: BlogConfig) {
super()

this.appInstance = appInstance
this.cfg = cfg
this.logger = createAppLogger("base-blog-api")
this.baseExtendApi = new BaseExtendApi(this)
Expand All @@ -67,6 +70,23 @@ export class BaseBlogApi extends BlogApi {
return await this.baseExtendApi.preEditPost(post, id, publishCfg)
}

public async apiFormFetch(url: string, headers: any[], formData: FormData) {
const win = this.appInstance.win
const doFetch = win.require(`${this.appInstance.moduleBase}libs/zhi-formdata-fetch/index.cjs`)

// headers
const header = headers.length > 0 ? headers[0] : {}
this.logger.debug("before zhi-formdata-fetch, headers =>", headers)
this.logger.debug("before zhi-formdata-fetch, url =>", url)

const resText = await doFetch(this.appInstance.moduleBase, url, header, formData)
this.logger.debug("apiForm doFetch success, resText =>", resText)
const resJson = JsonUtil.safeParse<any>(resText, {} as any)
this.logger.debug("apiForm doFetch success, resJson=>", resJson)

return resJson
}

// ================
// private methods
// ================
Expand Down
88 changes: 86 additions & 2 deletions src/adaptors/api/halo/HaloApiAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import { HaloConfig } from "~/src/adaptors/api/halo/HaloConfig.ts"
import { BaseBlogApi } from "~/src/adaptors/api/base/baseBlogApi.ts"
import { createAppLogger } from "~/src/utils/appLogger.ts"
import { CategoryInfo, Post, UserBlog } from "zhi-blog-api"
import { Attachment, CategoryInfo, MediaObject, Post, UserBlog } from "zhi-blog-api"
import { AliasTranslator, JsonUtil, ObjectUtil, StrUtil } from "zhi-common"
import { Base64 } from "js-base64"
import sypIdUtil from "~/src/utils/sypIdUtil.ts"
Expand Down Expand Up @@ -197,8 +197,13 @@ class HaloApiAdaptor extends BaseBlogApi {
params.post.spec.tags = tagNames
}

// 更新文章信息
await this.haloRequest(`/apis/content.halo.run/v1alpha1/posts/${name}`, params.post, "PUT")
await this.haloRequest(`/apis/api.console.halo.run/v1alpha1/posts/${name}/content`, params.content, "PUT")

// 重新发布
await this.haloRequest(`/apis/api.console.halo.run/v1alpha1/posts/${params.post.metadata.name}/publish`, {}, "PUT")
this.logger.debug("halo 文章发布完成")
} catch (e) {
this.logger.error("Halo文章更新失败", e)
}
Expand All @@ -215,6 +220,12 @@ class HaloApiAdaptor extends BaseBlogApi {
this.logger.debug("getPost haloPost =>", { name: name, haloPost: haloPost })

const commonPost = new Post()
commonPost.title = haloPost.post.spec.title
commonPost.wp_slug = haloPost.post.spec.slug
commonPost.shortDesc = haloPost.post.spec.excerpt.raw

commonPost.tags_slugs = haloPost.post.spec.tags.join(",")
commonPost.cate_slugs = haloPost.post.spec.categories

return commonPost
}
Expand Down Expand Up @@ -263,6 +274,66 @@ class HaloApiAdaptor extends BaseBlogApi {
return cats
}

public async newMediaObject(mediaObject: MediaObject, customHandler?: any): Promise<Attachment> {
let res: any
try {
const bits = mediaObject.bits
this.logger.debug("newMediaObject on halo =>", mediaObject)

// import
const win = this.appInstance.win
if (!win.require) {
throw new Error("非常抱歉,目前仅思源笔记PC客户端支持上传图片")
}
const { FormData, Blob } = win.require(`${this.appInstance.moduleBase}libs/node-fetch-cjs/dist/index.js`)
const blob = new Blob([bits], { type: mediaObject.type })

// uploadUrl
const uploadUrl = `${this.cfg.apiUrl}/apis/api.console.halo.run/v1alpha1/attachments/upload`

// formData
const formData = new FormData()
formData.append("file", blob, mediaObject.name)
formData.append("policyName", "default-policy")
formData.append("groupName", "")
formData.append("file", blob, mediaObject.name)

// 发送请求
res = await this.haloFormFetch(uploadUrl, formData)
this.logger.debug("halo upload success, res =>", res)
if (!res.metadata) {
throw new Error("Halo图片上传失败 =>" + mediaObject.name)
}
} catch (e) {
this.logger.error("Error uploading image to halo:", e)
}

const siteImgId = res?.spec?.displayName ?? ""
const siteArticleId = res?.metadata?.name ?? ""
const siteImgUrl = this.cfg.home + res?.metadata?.annotations["storage.halo.run/uri"] ?? ""
return {
attachment_id: siteImgId,
date_created_gmt: new Date(),
parent: 0,
link: siteImgUrl,
title: mediaObject.name,
caption: "",
description: "",
metadata: {
width: 0,
height: 0,
file: "",
filesize: 0,
sizes: [],
},
type: mediaObject.type,
thumbnail: "",
id: siteArticleId,
file: mediaObject.name,
url: siteImgUrl,
}
}

// ================
// private methods
// ================
Expand Down Expand Up @@ -393,18 +464,21 @@ class HaloApiAdaptor extends BaseBlogApi {
* @param url 请求地址
* @param params 数据
* @param method 请求方法 GET | POST | PUT | DELETE
* @param header 请求头
* @private
*/
private async haloRequest(
url: string,
params?: any,
method: "GET" | "POST" | "PUT" | "DELETE" = "POST"
method: "GET" | "POST" | "PUT" | "DELETE" = "POST",
header: Record<any, any> = {}
): Promise<any> {
const contentType = "application/json"
const basicAuth = "Basic " + Base64.btoa(this.cfg.username + ":" + this.cfg.password)
const headers = {
"Content-Type": contentType,
Authorization: basicAuth,
...header,
}

// 打印日志
Expand All @@ -419,6 +493,16 @@ class HaloApiAdaptor extends BaseBlogApi {

return resJson ?? null
}

private async haloFormFetch(url: string, formData: FormData) {
const basicAuth = "Basic " + Base64.btoa(this.cfg.username + ":" + this.cfg.password)
const header = {
Authorization: basicAuth,
}

const resJson = await this.apiFormFetch(url, [header], formData)
return resJson
}
}

export { HaloApiAdaptor }

0 comments on commit 3e13fb5

Please sign in to comment.