Skip to content

Commit

Permalink
feat: 掘金支持专栏作为分类
Browse files Browse the repository at this point in the history
  • Loading branch information
terwer committed Sep 7, 2023
1 parent 2d0d137 commit 546fec2
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 36 deletions.
4 changes: 2 additions & 2 deletions src/adaptors/web/juejin/juejinConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ export class JuejinConfig extends CommonWebConfig {
this.passwordType = PasswordType.PasswordType_Cookie
this.usernameEnabled = false
this.tagEnabled = true
this.cateEnabled = true
this.cateEnabled = false
this.categoryType = CategoryTypeEnum.CategoryType_Single
this.knowledgeSpaceEnabled = true
this.knowledgeSpaceTitle = "专栏"
this.knowledgeSpaceTitle = "分类"
this.knowledgeSpaceType = CategoryTypeEnum.CategoryType_Single
this.allowKnowledgeSpaceChange = false
this.placeholder.knowledgeSpaceReadonlyModeTip =
Expand Down
182 changes: 154 additions & 28 deletions src/adaptors/web/juejin/juejinWebAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import { BaseWebApi } from "~/src/adaptors/web/base/baseWebApi.ts"
import { CategoryInfo, Post, UserBlog } from "zhi-blog-api"
import { StrUtil } from "zhi-common"

/**
* 掘金网页授权适配器
Expand Down Expand Up @@ -56,23 +57,20 @@ class JuejinWebAdaptor extends BaseWebApi {
public async getUsersBlogs(): Promise<Array<UserBlog>> {
let result: UserBlog[] = []

const url = "https://api.juejin.cn/content_api/v1/column/author_center_list"
const params = {
audit_status: null,
page_no: 1,
page_size: 10,
const header = {
accept: "application/json",
}
const res = await this.webProxyFetch(url, [], params, "POST")
this.logger.debug("get juejin columns =>", { res })
const res = await this.webProxyFetch("https://api.juejin.cn/tag_api/v1/query_category_list", [header], {}, "POST")
this.logger.info(`get juejin categories`, res.data)

if (res.err_no === 0) {
const columns = res.data
columns.forEach((item: any) => {
if (res.data && res.data.length > 0) {
const cates = res.data
cates.forEach((item: any) => {
const useBlog = new UserBlog()

useBlog.blogid = item.column_id
useBlog.blogName = item.column_version.title
useBlog.url = item.column_version.cover
useBlog.blogid = item.category_id
useBlog.blogName = item.category.category_name
useBlog.url = item.category.icon
result.push(useBlog)
})
}
Expand All @@ -81,35 +79,163 @@ class JuejinWebAdaptor extends BaseWebApi {
return result
}

public async getCategories(): Promise<CategoryInfo[]> {
const cats = [] as CategoryInfo[]
public async addPost(post: Post) {
const cate_slug = post.cate_slugs?.[0] ?? this.cfg.blogid
if (StrUtil.isEmptyString(cate_slug)) {
throw new Error("掘金平台必须选择一个分类")
}

// 保存草稿
const draftUrl = "https://api.juejin.cn/content_api/v1/article_draft/create"
const draftParams = {
category_id: cate_slug,
tag_ids: [],
link_url: "",
cover_image: "",
title: post.title,
brief_content: post.shortDesc,
edit_type: 10,
html_content: "deprecated",
mark_content: post.description,
theme_ids: [],
}
const draftRes = await this.webProxyFetch(draftUrl, [], draftParams, "POST")
this.logger.debug("juejin add post =>", draftRes)
if (draftRes.err_no !== 0) {
throw new Error("掘金文章草稿保存错误 =>" + draftRes.err_msg)
}
const draftId = draftRes.data.id.toString()

// 发布文章
const pageId = await this.publishPost(draftId)
const postid = [pageId, draftId].join("_")
return {
status: "success",
post_id: postid,
}
}

public async editPost(postid: string, post: Post, publish?: boolean): Promise<boolean> {
const cate_slug = post.cate_slugs?.[0] ?? this.cfg.blogid
if (StrUtil.isEmptyString(cate_slug)) {
throw new Error("掘金平台必须选择一个分类")
}

const juejinPostKey = this.getJuejinPostidKey(postid)
// const pageId = juejinPostKey.pageId
const draftId = juejinPostKey.draftId

// 更新文章
const draftUpdateUrl = "https://api.juejin.cn/content_api/v1/article_draft/update"
const draftParams = {
id: draftId,
category_id: cate_slug,
tag_ids: [],
link_url: "",
cover_image: "",
title: post.title,
brief_content: post.shortDesc,
edit_type: 10,
html_content: "deprecated",
mark_content: post.markdown,
theme_ids: [],
}
// 更新草稿
const draftRes = await this.webProxyFetch(draftUpdateUrl, [], draftParams, "POST")
this.logger.debug("juejin update post =>", draftRes)
if (draftRes.err_no !== 0) {
throw new Error("掘金文章更新错误 =>" + draftRes.err_msg)
}

// 发布文章
await this.publishPost(draftId)

return true
}

public async getPreviewUrl(postid: string): Promise<string> {
const juejinPostKey = this.getJuejinPostidKey(postid)
const pageId = juejinPostKey.pageId
const postUrl = this.cfg.previewUrl.replace("[postid]", pageId)
return StrUtil.pathJoin(this.cfg.home ?? "", postUrl)
}

const url = "https://api.juejin.cn/content_api/v1/column/author_center_list"
public async deletePost(postid: string): Promise<boolean> {
const url = "https://api.juejin.cn/content_api/v1/article/delete"
const params = {
audit_status: null,
page_no: 1,
page_size: 10,
article_id: postid,
}
const res = await this.webProxyFetch(url, [], params, "POST")
this.logger.debug("get juejin columns =>", { res })
this.logger.debug("juejin delete post res =>", res)
if (res.err_no !== 0) {
throw new Error("掘金文章删除失败 =>" + res.err_msg)
}

return true
}

public async getCategories(): Promise<CategoryInfo[]> {
const cats = [] as CategoryInfo[]

const header = {
accept: "application/json",
}
const res = await this.webProxyFetch("https://api.juejin.cn/tag_api/v1/query_category_list", [header], {}, "POST")
this.logger.info(`get juejin categories`, res.data)

if (res.err_no === 0) {
const columns = res.data
columns.forEach((item: any) => {
if (res.data && res.data.length > 0) {
res.data.forEach((item: any) => {
const cat = new CategoryInfo()
cat.categoryId = item.column_id
cat.categoryName = item.column_version.title
cat.categoryId = item.category_id
cat.categoryName = item.category.category_name
cats.push(cat)
})
}

return cats
}
// ================
// private methods
// ================
/**
* 获取封装的postid
*
* @param postid
* @private postid
*/
private getJuejinPostidKey(postid: string): any {
let pageId: string
let draftId: string
if (postid.indexOf("_") > 0) {
const idArr = postid.split("_")
pageId = idArr[0]
draftId = idArr[1]
} else {
pageId = postid
}

public async addPost(post: Post) {}
return {
pageId: pageId,
draftId: draftId,
}
}

public async editPost(postid: string, post: Post, publish?: boolean): Promise<boolean> {
return false
private async publishPost(draftId: string) {
// 发布文章
const url = "https://api.juejin.cn/content_api/v1/article/publish"
const params = {
draft_id: draftId,
sync_to_org: false,
column_ids: [],
theme_ids: [],
}
const res = await this.webProxyFetch(url, [], params, "POST")
this.logger.debug("juejin publish post res =>", res)
if (res.err_no !== 0) {
throw new Error("掘金文章发布失败 =>" + res?.err_msg ?? res)
}

return res.data.article_id.toString()
}
}

Expand Down
9 changes: 3 additions & 6 deletions src/adaptors/web/juejin/useJuejinWeb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,11 @@ const useJuejinWeb = async (key?: string, newCfg?: JuejinConfig) => {

cfg.tagEnabled = true
// 掘金使用单选分类
cfg.cateEnabled = true
cfg.categoryType = CategoryTypeEnum.CategoryType_Single
cfg.cateEnabled = false
cfg.knowledgeSpaceEnabled = true
cfg.knowledgeSpaceTitle = "专栏"
cfg.knowledgeSpaceTitle = "分类"
cfg.knowledgeSpaceType = CategoryTypeEnum.CategoryType_Single
cfg.allowKnowledgeSpaceChange = false
cfg.placeholder.knowledgeSpaceReadonlyModeTip =
"由于掘金平台的限制,暂时不支持编辑所属专栏。如果您想移动文档,请先点击取消删除该文档,然后重新选择新的专栏发布"
cfg.allowKnowledgeSpaceChange = true

const webApi = new JuejinWebAdaptor(appInstance, cfg)
return {
Expand Down
77 changes: 77 additions & 0 deletions testdata/juejin/juejin.http
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,80 @@ Content-Type: application/json
"page_size": 10
}

### 获取文章详情
POST https://api.juejin.cn/content_api/v1/article/detail?aid=2608
Cookie: {{cookie}}
Content-Type: application/json

{
"article_id": "7275943600780935209"
}

### 保存文章草稿
POST https://api.juejin.cn/content_api/v1/article_draft/create
Cookie: {{cookie}}
Content-Type: application/json

{
"category_id": "6809637769959178254",
"tag_ids": [
"6809640407484334093"
],
"link_url": "",
"cover_image": "",
"title": "cesssss3",
"brief_content": "dfgdfgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg",
"edit_type": 10,
"html_content": "deprecated",
"mark_content": "",
"theme_ids": []
}

### 更新草稿
POST https://api.juejin.cn/content_api/v1/article_draft/update?aid=2608&uuid=7267424099298854436
Cookie: {{cookie}}
Content-Type: application/json

{
"id": "7275934458133545001",
"category_id": "6809637769959178254",
"tag_ids": [
"6809640407484334093"
],
"link_url": "",
"cover_image": "",
"title": "cesssss3",
"brief_content": "dfgdfgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg",
"edit_type": 10,
"html_content": "deprecated",
"mark_content": "dfgfdgdfgdfgdfgdfgfddfgdf7f",
"theme_ids": []
}

### 发布草稿
POST https://api.juejin.cn/content_api/v1/article/publish
Cookie: {{cookie}}
Content-Type: application/json

{
"draft_id": "7275945995623792679",
"sync_to_org": false,
"column_ids": [],
"theme_ids": []
}

### 删除文章
POST https://api.juejin.cn/content_api/v1/article/delete
cookie: {{cookie}}
Content-Type: application/json

{
"article_id": "7275943600781164585"
}

### 获取分类
POST https://api.juejin.cn/tag_api/v1/query_category_list
cookie: {{cookie}}
Content-Type: application/json

{}

0 comments on commit 546fec2

Please sign in to comment.