Skip to content

Commit

Permalink
Merge pull request #1549 from terwer/dev
Browse files Browse the repository at this point in the history
fix halo auth error in some cases
  • Loading branch information
terwer authored Dec 21, 2024
2 parents 27c186c + ebe8a27 commit 16c5891
Show file tree
Hide file tree
Showing 39 changed files with 307 additions and 1,024 deletions.
11 changes: 11 additions & 0 deletions src/adaptors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import { useJvueApi } from "~/src/adaptors/api/jvue/useJvueApi.ts"
import { useWordpressdotcomApi } from "~/src/adaptors/api/wordpress-dot-com/useWordpressdotcomApi.ts"
import { useHalowebWeb } from "~/src/adaptors/web/haloweb/useHalowebWeb.ts"
import { useBilibiliWeb } from "~/src/adaptors/web/bilibili/useBilibiliWeb.ts"
import { useXiaohongshuWeb } from "~/src/adaptors/web/xiaohongshu/useXiaohongshuWeb.ts"

/**
* 适配器统一入口
Expand Down Expand Up @@ -228,6 +229,11 @@ class Adaptors {
conf = cfg
break
}
case SubPlatformType.Custom_Xiaohongshu: {
const { cfg } = await useXiaohongshuWeb(key)
conf = cfg
break
}
case SubPlatformType.System_Siyuan: {
const { siyuanConfig } = useSiyuanApi()
conf = siyuanConfig
Expand Down Expand Up @@ -403,6 +409,11 @@ class Adaptors {
blogAdaptor = webApi
break
}
case SubPlatformType.Custom_Xiaohongshu: {
const { webApi } = await useXiaohongshuWeb(key, newCfg)
blogAdaptor = webApi
break
}
case SubPlatformType.System_Siyuan: {
const { blogApi } = useSiyuanApi()
blogAdaptor = blogApi
Expand Down
6 changes: 6 additions & 0 deletions src/adaptors/web/bilibili/bilibiliWebAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ import { JsonUtil, StrUtil } from "zhi-common"
import { MockBrowser } from "~/src/utils/MockBrowser.ts"
import { fileToBuffer } from "~/src/utils/polyfillUtils.ts"

/**
* Bilibili 平台适配器
*
* @author terwer
* @since v1.31.0
*/
class BilibiliWebAdaptor extends BaseWebApi {
private bilibiliMetaDataCfg = {} as any

Expand Down
2 changes: 1 addition & 1 deletion src/adaptors/web/haloweb/HalowebWebAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import HaloUtils from "~/src/adaptors/api/halo/haloUtils.ts"
class HalowebWebAdaptor extends BaseWebApi {
public async getMetaData(): Promise<any> {
const res = await this.halowebFetch("/actuator/globalinfo")
const flag = !!res.externalUrl
const flag = !StrUtil.isEmptyString(res?.siteTitle)
this.logger.info(`get haloweb metadata finished, flag => ${flag}`)
return {
flag: flag,
Expand Down
9 changes: 9 additions & 0 deletions src/adaptors/web/xiaohongshu/XiaohongshuUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* Copyright (C) 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.
*/

92 changes: 92 additions & 0 deletions src/adaptors/web/xiaohongshu/XiaohongshuWebAdaptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* Copyright (C) 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 { BaseWebApi } from "~/src/adaptors/web/base/baseWebApi.ts"
import { StrUtil } from "zhi-common"
import { MockBrowser } from "~/src/utils/MockBrowser.ts"

/**
* 小红书适配器
*
* @author terwer
* @since 1.32.0
*/
class XiaohongshuWebAdaptor extends BaseWebApi {
public async getMetaData(): Promise<any> {
// "/api/galaxy/user/info"
// "/api/galaxy/user/my-info"
const header = {
"User-Agent": MockBrowser.HEADERS.MACOS_CHROME["User-Agent"],
referer: "https://creator.xiaohongshu.com/publish/publish?from=menu",
}
const res = await this.xiaohongshuFetch("/api/galaxy/user/my-info", header)
// const flag = !!res?.data?.user_id
this.logger.debug("get xiaohongshu metadata finished=>", res)
throw new Error("开发中。。。")
}

// ================
// private methods
// ================

private async xiaohongshuFetch(
url: string,
headers: any = {},
params: any = undefined,
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" = "GET",
contentType: string = "application/json"
) {
const apiUrl = StrUtil.pathJoin(this.cfg.apiUrl, url)
const reqHeaderMap = new Map<string, string>()
reqHeaderMap.set("Cookie", this.cfg.password)

const mergedHeaders = {
...Object.fromEntries(reqHeaderMap),
...headers,
}

const body = params

// 构建请求选项
const requestOptions: RequestInit = {
method: method,
headers: mergedHeaders,
body: params,
}

// 发送请求并返回响应
this.logger.debug("xiaohongshu url =>", apiUrl)
this.logger.debug("xiaohongshu requestOptions =>", requestOptions)
const res = await this.webFetch(apiUrl, [mergedHeaders], body, method, contentType, true, "base64", "text")
return res
}

private async xiaohongshuFormFetch(url: string, formData: BodyInit) {
const apiUrl = StrUtil.pathJoin(this.cfg.apiUrl, url)
const reqHeaderMap = new Map<string, string>()
reqHeaderMap.set("Cookie", this.cfg.password)

// header
const mergedHeaders = {
Cookie: this.cfg.password,
}

const options: RequestInit = {
method: "POST",
headers: mergedHeaders,
body: formData,
}
this.logger.debug("xiaohongshu form url =>", apiUrl)
this.logger.debug("xiaohongshu form options =>", options)
const res = await this.webFormFetch(apiUrl, [mergedHeaders], formData, true)
return res
}
}

export { XiaohongshuWebAdaptor }
74 changes: 74 additions & 0 deletions src/adaptors/web/xiaohongshu/useXiaohongshuWeb.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* Copyright (C) 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 { JsonUtil, ObjectUtil, StrUtil } from "zhi-common"
import { XiaohongshuWebAdaptor } from "./XiaohongshuWebAdaptor"
import { getDynPostidKey } from "~/src/platforms/dynamicConfig.ts"
import { Utils } from "~/src/utils/utils"
import { LEGENCY_SHARED_PROXT_MIDDLEWARE } from "~/src/utils/constants.ts"
import { usePublishSettingStore } from "~/src/stores/usePublishSettingStore.ts"
import { XiaohongshuConfig } from "~/src/adaptors/web/xiaohongshu/xiaohongshuConfig.ts"
import { PublisherAppInstance } from "~/src/publisherAppInstance.ts"
import { createAppLogger } from "~/src/utils/appLogger.ts"

/**
* 用于获取小红书的API的自定义Hook
*
* @param key - 平台 key
* @param newCfg - 可选参数,用于指定新的配置
*/
const useXiaohongshuWeb = async (key?: string, newCfg?: XiaohongshuConfig) => {
// 创建应用日志记录器
const logger = createAppLogger("use-xiaohongshu-web")

// 记录开始使用小红书 WebAuth
logger.info("Start using Xiaohongshu WebAuth...")

// 创建应用实例
const appInstance = new PublisherAppInstance()
let cfg: XiaohongshuConfig
if (newCfg) {
logger.info("Initialize with the latest newCfg passed in...")
cfg = newCfg
} else {
// 从配置中获取数据
const { getSetting } = usePublishSettingStore()
const setting = await getSetting()
cfg = JsonUtil.safeParse<XiaohongshuConfig>(setting[key], {} as XiaohongshuConfig)
// 如果配置为空,则使用默认的环境变量值,并记录日志
if (ObjectUtil.isEmptyObject(cfg)) {
// 从环境变量获取小红书的cookie
const middlewareUrl = Utils.emptyOrDefault(process.env.VITE_MIDDLEWARE_URL, LEGENCY_SHARED_PROXT_MIDDLEWARE)
const xiaohongshuCookie = Utils.emptyOrDefault(process.env.VITE_XIAOHONGSHU_AUTH_TOKEN, "")
cfg = new XiaohongshuConfig(xiaohongshuCookie, middlewareUrl)
logger.debug("Configuration is empty, using default environment variables.")
} else {
logger.info("Using configuration from settings...")
}
const middlewareUrl = Utils.emptyOrDefault(process.env.VITE_MIDDLEWARE_URL, LEGENCY_SHARED_PROXT_MIDDLEWARE)
if (StrUtil.isEmptyString(cfg.middlewareUrl)) {
cfg.middlewareUrl = middlewareUrl
}
// 初始化posidKey
if (StrUtil.isEmptyString(cfg.posidKey)) {
// 默认值
cfg.posidKey = getDynPostidKey(key)
}
}

// 小红书其他配置

const webApi = new XiaohongshuWebAdaptor(appInstance, cfg)
return {
cfg,
webApi,
}
}

export { useXiaohongshuWeb }
30 changes: 30 additions & 0 deletions src/adaptors/web/xiaohongshu/xiaohongshuPlaceholder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2024, Terwer . All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Terwer designates this
* particular file as subject to the "Classpath" exception as provided
* by Terwer in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Terwer, Shenzhen, Guangdong, China, [email protected]
* or visit www.terwer.space if you need additional information or have any
* questions.
*/

import { CommonWebPlaceholder } from "~/src/adaptors/web/base/commonWebPlaceholder.ts"

class XiaohongshuPlaceholder extends CommonWebPlaceholder {}

export { XiaohongshuPlaceholder }
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,9 @@ const _handleValidateOpenBrowserAuth = (dynCfg: DynamicConfig) => {
formData.webAuthLoadingMap[dynCfg.platformKey] = false
}

openBrowserWindow(dynCfg.authUrl, dynCfg, cookieCb)
const extraScriptCb = () => {}

openBrowserWindow(dynCfg.authUrl, dynCfg, cookieCb, extraScriptCb)
}

const _handleClearAuthConfirm = (msg, url: string) => {
Expand Down
3 changes: 3 additions & 0 deletions src/platforms/PreConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
const PRE_COMTANTS = {
PRE_CUSTOM_HALOWEB: "custom_Haloweb",
PRE_CUSTOM_BILIBILI: "custom_Bilibili",
PRE_CUSTOM_XIAOHONGSHU: "custom_Xiaohongshu",
// PRE_CUSTOM_WEIBO: "custom_Weibo",
// PRE_CUSTOM_TOUTIAO: "custom_Toutiao",
}

export { PRE_COMTANTS }
10 changes: 10 additions & 0 deletions src/platforms/dynamicConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ export class DynamicConfig {
*/
isSys: boolean

/**
* 额外脚本,用于自定义平台,例如:小红书
*
* @author terwer
* @since 1.32.0
*/
extraScript?: string

constructor(
platformType: PlatformType,
platformKey: string,
Expand Down Expand Up @@ -216,6 +224,7 @@ export enum SubPlatformType {
// Custom_Flowus = "Flowus",
Custom_Haloweb = "Haloweb",
Custom_Bilibili = "Bilibili",
Custom_Xiaohongshu = "Xiaohongshu",

// System
System_Siyuan = "Siyuan",
Expand Down Expand Up @@ -285,6 +294,7 @@ export function getSubtypeList(ptype: PlatformType): SubPlatformType[] {
// subtypeList.push(SubPlatformType.Custom_Flowus)
subtypeList.push(SubPlatformType.Custom_Haloweb)
subtypeList.push(SubPlatformType.Custom_Bilibili)
subtypeList.push(SubPlatformType.Custom_Xiaohongshu)
break
case PlatformType.System:
subtypeList.push(SubPlatformType.System_Siyuan)
Expand Down
22 changes: 21 additions & 1 deletion src/platforms/pre.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AuthMode, DynamicConfig, PlatformType, SubPlatformType } from "~/src/platforms/dynamicConfig.ts"
import { svgIcons } from "~/src/utils/svgIcons.ts"
import { PRE_COMTANTS } from "~/src/platforms/PreConstants.ts"
import { MockBrowser } from "~/src/utils/MockBrowser.ts"

/**
* 一些因为政策原因必须要特殊处理的平台
Expand All @@ -9,7 +10,7 @@ export const extraPreCfg = {
// 白名单(作用是以前限制了,但是后来可用的情况,以前就能用的和新平台不必加)
cookieWhiteList: [SubPlatformType.Custom_Wechat.toString(), SubPlatformType.Custom_Zhihu.toString()],
// UA白名单(有 UA 限制的必须加,而且是慎之又慎)
uaWhiteList: ["https://*.qq.com/*", "https://*.bilibili.com/*"],
uaWhiteList: ["https://*.qq.com/*", "https://*.bilibili.com/*", "https://*.xiaohongshu.com/*"],
// 黑名单
cookieLimit: [
// SubPlatformType.Custom_Wechat.toString()
Expand All @@ -23,6 +24,13 @@ export const extraPreCfg = {
// [SubPlatformType.Custom_Wechat.toString()]: "https://img1.terwer.space/api/public/202309051734289.png",
// [SubPlatformType.Custom_Zhihu.toString()]: "https://img1.siyuan.wiki/api/vip/open/media/aHR0cHM6Ly9jZG4uc2EubmV0LzIwMjQvMTEvMjYvdFpmSWp6VjE2U3U4djRXLnBuZw==",
},
// 这里需要全路径匹配,没有使用默认的,只增加 UA
headersMap: {
// "https://www.xiaohongshu.com/login": {
// "User-Agent": MockBrowser.HEADERS.MACOS_CHROME["User-Agent"],
// Referer: "https://creator.xiaohongshu.com/publish/publish?from=menu",
// },
},
}

/**
Expand Down Expand Up @@ -361,6 +369,18 @@ export const pre = {
domain: "bilibili.com",
isEnabled: false,
},
// {
// platformType: PlatformType.Custom,
// subPlatformType: SubPlatformType.Custom_Xiaohongshu,
// platformKey: PRE_COMTANTS.PRE_CUSTOM_XIAOHONGSHU,
// platformName: "小红书",
// platformIcon: svgIcons.iconIFXiaohongshu,
// authMode: AuthMode.WEBSITE,
// authUrl: "https://www.xiaohongshu.com/login",
// domain: "xiaohongshu.com",
// isEnabled: false,
// extraScript: `(function() { console.log("xiaohongshu适配成功") })();`,
// },
],
systemCfg: <DynamicConfig[]>[
{
Expand Down
Loading

0 comments on commit 16c5891

Please sign in to comment.