@gengchenchina/chrome-media-publish-extension 1.0.8 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -509,6 +509,11 @@ Manager 发布菜单会自动递增 patch;工具包若首发为 `1.0.9`,则
509
509
 
510
510
  ## Adapter 开发规范
511
511
 
512
+ 百家号编辑页跳到 STOKEN 中间页时,内核会自动执行 Passport 获取 STOKEN、`dealtoken` 和一次编辑页重试。
513
+ 真实账号验证步骤与失败诊断见 `docs/integration-guide.md` 的“百家号 STOKEN 补全与修复验证”。
514
+ 本次还补充了 Passport STOKEN 接口的百家号 Referer 规则,以处理 `errno=12 / invalid refer`。
515
+ 已发布版本不会自动包含本地新修复;发布前查询版本并递增,然后更新下游依赖、重建并重新加载扩展。
516
+
512
517
  真实平台 adapter 放在:
513
518
 
514
519
  ```text
package/dist/index.js CHANGED
@@ -4126,6 +4126,9 @@ var BAIJIAHAO_PLATFORM = Platform.Baijiahao;
4126
4126
  var BAIJIAHAO_ORIGIN = "https://baijiahao.baidu.com";
4127
4127
  var BAIJIAHAO_APPINFO_URL = `${BAIJIAHAO_ORIGIN}/builder/app/appinfo`;
4128
4128
  var BAIJIAHAO_EDIT_URL = `${BAIJIAHAO_ORIGIN}/builder/rc/edit`;
4129
+ var BAIJIAHAO_STOKEN_URL = `${BAIJIAHAO_ORIGIN}/builder/fe-react/stoken.html`;
4130
+ var BAIJIAHAO_PASSPORT_AUTH_URL = "https://passport.baidu.com/v3/login/api/auth/";
4131
+ var BAIJIAHAO_DEALTOKEN_URL = `${BAIJIAHAO_ORIGIN}/pcui/home/dealtoken`;
4129
4132
  var BAIJIAHAO_ARTICLE_PUBLISH_URL = `${BAIJIAHAO_ORIGIN}/pcui/article/publish`;
4130
4133
  var BAIJIAHAO_ARTICLE_LIST_URL = `${BAIJIAHAO_ORIGIN}/pcui/article/lists`;
4131
4134
  var BAIJIAHAO_IMAGE_UPLOAD_URL = `${BAIJIAHAO_ORIGIN}/pcui/picture/uploadproxy`;
@@ -4137,6 +4140,12 @@ var BAIJIAHAO_HEADER_RULES = Object.freeze([
4137
4140
  Referer: `${BAIJIAHAO_ORIGIN}/`
4138
4141
  }),
4139
4142
  resourceTypes: Object.freeze(["xmlhttprequest"])
4143
+ }),
4144
+ Object.freeze({
4145
+ // Passport 校验 STOKEN 请求来源;只覆盖此接口,保持其他 Passport 请求不变。
4146
+ urlFilter: `|${BAIJIAHAO_PASSPORT_AUTH_URL}`,
4147
+ headers: Object.freeze({ Referer: `${BAIJIAHAO_ORIGIN}/` }),
4148
+ resourceTypes: Object.freeze(["xmlhttprequest"])
4140
4149
  })
4141
4150
  ]);
4142
4151
  var BAIJIAHAO_SKIP_IMAGE_HOSTS = Object.freeze([
@@ -4154,7 +4163,9 @@ async function fetchText(ctx, url, init = {}, options = {}) {
4154
4163
  Accept: "application/json, text/plain, */*",
4155
4164
  ...init.headers || {}
4156
4165
  },
4157
- body: init.body
4166
+ body: init.body,
4167
+ ...init.cache ? { cache: init.cache } : {},
4168
+ ...init.redirect ? { redirect: init.redirect } : {}
4158
4169
  }, { timeoutMs: options.timeoutMs });
4159
4170
  const text = await response.text();
4160
4171
  options.onResponse?.(response, text);
@@ -4616,14 +4627,7 @@ function createArticleDependencies(ctx, input) {
4616
4627
  async function fetchBaijiahaoAuthToken(ctx, input = {}) {
4617
4628
  const startedAt = Date.now();
4618
4629
  let httpErrorCode;
4619
- const diagnostics = {
4620
- schemaVersion: 1,
4621
- stage: "baijiahao.auth-token",
4622
- failure: "REQUEST_FAILED",
4623
- requestedAt: new Date(startedAt).toISOString(),
4624
- requestUrl: BAIJIAHAO_EDIT_URL,
4625
- requestAccept: "application/json, text/plain, */*",
4626
- credentials: "include",
4630
+ const emptyResponse = {
4627
4631
  status: null,
4628
4632
  finalUrl: null,
4629
4633
  redirected: null,
@@ -4633,13 +4637,26 @@ async function fetchBaijiahaoAuthToken(ctx, input = {}) {
4633
4637
  tokenMatched: null,
4634
4638
  hasHtmlMarkers: null,
4635
4639
  hasLoginMarkers: null,
4636
- hasChallengeMarkers: null,
4640
+ hasChallengeMarkers: null
4641
+ };
4642
+ const diagnostics = {
4643
+ schemaVersion: 1,
4644
+ stage: "baijiahao.auth-token",
4645
+ failure: "REQUEST_FAILED",
4646
+ requestedAt: new Date(startedAt).toISOString(),
4647
+ requestUrl: BAIJIAHAO_EDIT_URL,
4648
+ requestAccept: "application/json, text/plain, */*",
4649
+ credentials: "include",
4650
+ ...emptyResponse,
4637
4651
  elapsedMs: 0
4638
4652
  };
4639
- try {
4640
- const html = await fetchText(ctx, BAIJIAHAO_EDIT_URL, {
4641
- credentials: "include"
4642
- }, {
4653
+ const requestText = (url, init = {}) => {
4654
+ httpErrorCode = void 0;
4655
+ Object.assign(diagnostics, emptyResponse, {
4656
+ requestUrl: url.split("?")[0],
4657
+ failure: "REQUEST_FAILED"
4658
+ });
4659
+ return fetchText(ctx, url, { credentials: "include", ...init }, {
4643
4660
  timeoutMs: input.timeoutMs,
4644
4661
  includeErrorBody: false,
4645
4662
  onResponse(response, text) {
@@ -4650,8 +4667,8 @@ async function fetchBaijiahaoAuthToken(ctx, input = {}) {
4650
4667
  }
4651
4668
  let finalUrl = null;
4652
4669
  try {
4653
- const url = new URL(response.url);
4654
- finalUrl = `${url.origin}${url.pathname}`;
4670
+ const url2 = new URL(response.url);
4671
+ finalUrl = `${url2.origin}${url2.pathname}`;
4655
4672
  } catch {
4656
4673
  }
4657
4674
  Object.assign(diagnostics, {
@@ -4667,9 +4684,75 @@ async function fetchBaijiahaoAuthToken(ctx, input = {}) {
4667
4684
  hasLoginMarkers: /passport\.baidu\.com|登录|\blogin\b/i.test(text),
4668
4685
  hasChallengeMarkers: /验证码|安全验证|安全校验|\bcaptcha\b/i.test(text)
4669
4686
  });
4687
+ if (diagnostics.sessionRefresh?.phase === "passport") {
4688
+ diagnostics.sessionRefresh.authStatus = response.status;
4689
+ } else if (diagnostics.sessionRefresh?.phase === "dealtoken") {
4690
+ diagnostics.sessionRefresh.dealtokenStatus = response.status;
4691
+ }
4670
4692
  }
4671
4693
  });
4672
- const match = html.match(/window\.__BJH__INIT__AUTH__\s*=\s*['"]([^'"]+)['"]/);
4694
+ };
4695
+ const matchToken = (html) => html.match(/window\.__BJH__INIT__AUTH__\s*=\s*['"]([^'"]+)['"]/);
4696
+ try {
4697
+ let html = await requestText(BAIJIAHAO_EDIT_URL);
4698
+ let match = matchToken(html);
4699
+ if (!match && diagnostics.finalUrl === BAIJIAHAO_STOKEN_URL) {
4700
+ diagnostics.sessionRefresh = {
4701
+ attempted: true,
4702
+ completed: false,
4703
+ phase: "passport",
4704
+ authStatus: null,
4705
+ authErrno: null,
4706
+ dealtokenStatus: null
4707
+ };
4708
+ const callback = `json_callback_${Date.now()}`;
4709
+ const params = new URLSearchParams({ callback, return_type: "2", tpl: "bjh" });
4710
+ const authText = await requestText(`${BAIJIAHAO_PASSPORT_AUTH_URL}?${params}`, { cache: "no-store" });
4711
+ let auth;
4712
+ try {
4713
+ const jsonp = authText.trim().match(new RegExp(`^${callback}\\s*\\(([\\s\\S]*)\\)\\s*;?$`));
4714
+ auth = JSON.parse(jsonp ? jsonp[1] : authText);
4715
+ if (!auth || typeof auth !== "object" || Array.isArray(auth)) throw new Error();
4716
+ } catch {
4717
+ diagnostics.failure = "STOKEN_RESPONSE_INVALID";
4718
+ throw new Error("\u767E\u5BB6\u53F7 Passport STOKEN \u54CD\u5E94\u683C\u5F0F\u5F02\u5E38");
4719
+ }
4720
+ const errno = typeof auth.errno === "number" || typeof auth.errno === "string" && /^-?\d+$/.test(auth.errno) ? Number(auth.errno) : NaN;
4721
+ diagnostics.sessionRefresh.authErrno = Number.isFinite(errno) ? errno : null;
4722
+ if (errno === 12) {
4723
+ diagnostics.failure = "STOKEN_REFERER_REJECTED";
4724
+ throw new Error("\u767E\u5BB6\u53F7 Passport \u8BF7\u6C42\u6765\u6E90\u6821\u9A8C\u5931\u8D25\uFF08errno=12\uFF09\uFF0C\u8BF7\u66F4\u65B0\u53D1\u6587\u6269\u5C55\u540E\u91CD\u8BD5");
4725
+ }
4726
+ const stoken = typeof auth.stoken === "string" ? auth.stoken.trim() : "";
4727
+ if (errno !== 0 || !/^[\x21-\x7e]+$/.test(stoken)) {
4728
+ diagnostics.failure = "STOKEN_AUTH_FAILED";
4729
+ throw new Error(`\u767E\u5BB6\u53F7 STOKEN \u83B7\u53D6\u5931\u8D25\uFF08Passport errno=${diagnostics.sessionRefresh.authErrno ?? "\u672A\u77E5"}\uFF09\uFF0C\u8BF7\u5728\u5E73\u53F0\u9875\u9762\u5B8C\u6210\u767B\u5F55\u6216\u9A8C\u8BC1\u540E\u91CD\u8BD5`);
4730
+ }
4731
+ diagnostics.sessionRefresh.phase = "dealtoken";
4732
+ await requestText(BAIJIAHAO_DEALTOKEN_URL, {
4733
+ headers: { bjh: stoken },
4734
+ cache: "no-store",
4735
+ redirect: "error"
4736
+ });
4737
+ if (diagnostics.sessionRefresh.dealtokenStatus !== 200 || diagnostics.redirected === true || diagnostics.finalUrl !== null && diagnostics.finalUrl !== BAIJIAHAO_DEALTOKEN_URL) {
4738
+ diagnostics.failure = "STOKEN_REFRESH_FAILED";
4739
+ throw new Error("\u767E\u5BB6\u53F7 STOKEN \u4F1A\u8BDD\u8865\u5168\u672A\u6210\u529F");
4740
+ }
4741
+ diagnostics.sessionRefresh.completed = true;
4742
+ diagnostics.sessionRefresh.phase = "retry-edit";
4743
+ html = await requestText(BAIJIAHAO_EDIT_URL, { cache: "no-store" });
4744
+ match = matchToken(html);
4745
+ if (!match) {
4746
+ const repeatedRedirect = diagnostics.finalUrl === BAIJIAHAO_STOKEN_URL;
4747
+ diagnostics.failure = repeatedRedirect ? "STOKEN_REDIRECT_LOOP" : "TOKEN_NOT_FOUND";
4748
+ throw new Error(repeatedRedirect ? "\u767E\u5BB6\u53F7 STOKEN \u8865\u5168\u540E\u4ECD\u8DF3\u8F6C\u5230\u4F1A\u8BDD\u521D\u59CB\u5316\u9875\uFF0C\u8BF7\u5728\u5E73\u53F0\u9875\u9762\u5B8C\u6210\u767B\u5F55\u6216\u9A8C\u8BC1\u540E\u91CD\u8BD5" : "\u767E\u5BB6\u53F7\u4F1A\u8BDD\u8865\u5168\u540E\u672A\u80FD\u83B7\u53D6\u7F16\u8F91\u9875\u53D1\u5E03 token");
4749
+ }
4750
+ ctx.Logger?.info?.("\u767E\u5BB6\u53F7 STOKEN \u4F1A\u8BDD\u8865\u5168\u6210\u529F", {
4751
+ stage: "baijiahao.auth-token",
4752
+ ...diagnostics.sessionRefresh,
4753
+ elapsedMs: Date.now() - startedAt
4754
+ });
4755
+ }
4673
4756
  if (!match) throw new Error("\u767B\u5F55\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55\u767E\u5BB6\u53F7");
4674
4757
  return match[1];
4675
4758
  } catch (error) {