feat(publish): add seven publish adapters for new media platforms

Wire sohuhao, wangyihao, juejin, smzdm, weixin-gzh, zol, and dongchedi
into the publish runtime: each ships its own publish protocol and
auth-failure classifier (login/token/challenge codes) plus registry
entries in selectPublishAdapter and the auth adapter map. Smzdm bind
detection now triple-falls-back across page-context fetch, session
fetch, cookie fetch, and a final cookie-derived account so the
nickname-less guest profile still resolves to a stable platform UID.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-27 00:57:37 +08:00
parent 34e54b9f78
commit 290da7cd50
14 changed files with 4997 additions and 17 deletions
@@ -115,6 +115,20 @@ function classifyBaijiahaoFailure(input: PlatformFailureInput): PlatformFailureC
return classifyFailure(input);
}
function classifySohuhaoFailure(input: PlatformFailureInput): PlatformFailureClassification {
const code = typeof input.error?.code === "string" ? input.error.code : "";
if (code === "sohuhao_not_logged_in") {
return "auth_failure";
}
if (code === "sohuhao_challenge_required") {
return "challenge";
}
if (code.startsWith("sohuhao_")) {
return "ok";
}
return classifyFailure(input);
}
function classifyQiehaoFailure(input: PlatformFailureInput): PlatformFailureClassification {
const code = typeof input.error?.code === "string" ? input.error.code : "";
if (code === "qiehao_challenge_required") {
@@ -140,6 +154,73 @@ function classifyBilibiliFailure(input: PlatformFailureInput): PlatformFailureCl
return classifyFailure(input);
}
function classifyJuejinFailure(input: PlatformFailureInput): PlatformFailureClassification {
const code = typeof input.error?.code === "string" ? input.error.code : "";
if (code === "juejin_not_logged_in") {
return "auth_failure";
}
if (code.startsWith("juejin_")) {
return "ok";
}
return classifyFailure(input);
}
function classifyWangyihaoFailure(input: PlatformFailureInput): PlatformFailureClassification {
const code = typeof input.error?.code === "string" ? input.error.code : "";
if (code === "wangyihao_not_logged_in" || code === "wangyihao_token_missing") {
return "auth_failure";
}
if (code === "wangyihao_challenge_required") {
return "challenge";
}
if (code.startsWith("wangyihao_")) {
return "ok";
}
return classifyFailure(input);
}
function classifyWeixinGzhFailure(input: PlatformFailureInput): PlatformFailureClassification {
const code = typeof input.error?.code === "string" ? input.error.code : "";
if (code === "weixin_gzh_not_logged_in") {
return "auth_failure";
}
if (code === "weixin_gzh_challenge_required") {
return "challenge";
}
if (code.startsWith("weixin_gzh_")) {
return "ok";
}
return classifyFailure(input);
}
function classifyZolFailure(input: PlatformFailureInput): PlatformFailureClassification {
const code = typeof input.error?.code === "string" ? input.error.code : "";
if (code === "zol_not_logged_in") {
return "auth_failure";
}
if (code === "zol_challenge_required") {
return "challenge";
}
if (code.startsWith("zol_")) {
return "ok";
}
return classifyFailure(input);
}
function classifyDongchediFailure(input: PlatformFailureInput): PlatformFailureClassification {
const code = typeof input.error?.code === "string" ? input.error.code : "";
if (code === "dongchedi_not_logged_in") {
return "auth_failure";
}
if (code === "dongchedi_challenge_required") {
return "challenge";
}
if (code.startsWith("dongchedi_")) {
return "ok";
}
return classifyFailure(input);
}
const genericAdapter: PlatformAdapter = {
async probe(account, partition) {
return await probePublishAccountSession(account, partition);
@@ -180,6 +261,16 @@ const baijiahaoAdapter: PlatformAdapter = {
classifyFailure: classifyBaijiahaoFailure,
};
const sohuhaoAdapter: PlatformAdapter = {
async probe(account, partition) {
return await probePublishAccountSession(account, partition);
},
async silentRefresh(account, partition) {
return await silentRefreshPublishAccountSession(account, partition);
},
classifyFailure: classifySohuhaoFailure,
};
const qiehaoAdapter: PlatformAdapter = {
async probe(account, partition) {
return await probePublishAccountSession(account, partition);
@@ -200,12 +291,62 @@ const bilibiliAdapter: PlatformAdapter = {
classifyFailure: classifyBilibiliFailure,
};
const wangyihaoAdapter: PlatformAdapter = {
async probe(account, partition) {
return await probePublishAccountSession(account, partition);
},
async silentRefresh(account, partition) {
return await silentRefreshPublishAccountSession(account, partition);
},
classifyFailure: classifyWangyihaoFailure,
};
const juejinAdapter: PlatformAdapter = {
async probe(account, partition) {
return await probePublishAccountSession(account, partition);
},
async silentRefresh(account, partition) {
return await silentRefreshPublishAccountSession(account, partition);
},
classifyFailure: classifyJuejinFailure,
};
const weixinGzhAdapter: PlatformAdapter = {
async probe(account, partition) {
return await probePublishAccountSession(account, partition);
},
async silentRefresh(account, partition) {
return await silentRefreshPublishAccountSession(account, partition);
},
classifyFailure: classifyWeixinGzhFailure,
};
const zolAdapter: PlatformAdapter = {
async probe(account, partition) {
return await probePublishAccountSession(account, partition);
},
async silentRefresh(account, partition) {
return await silentRefreshPublishAccountSession(account, partition);
},
classifyFailure: classifyZolFailure,
};
const dongchediAdapter: PlatformAdapter = {
async probe(account, partition) {
return await probePublishAccountSession(account, partition);
},
async silentRefresh(account, partition) {
return await silentRefreshPublishAccountSession(account, partition);
},
classifyFailure: classifyDongchediFailure,
};
const adapterRegistry = new Map<string, PlatformAdapter>(
[
...aiPlatformCatalog.map((platform) => platform.id),
"toutiaohao",
"baijiahao",
"sohu",
"sohuhao",
"qiehao",
"zhihu",
"wangyihao",
@@ -224,11 +365,23 @@ const adapterRegistry = new Map<string, PlatformAdapter>(
? wenxinAdapter
: platform === "baijiahao"
? baijiahaoAdapter
: platform === "qiehao"
? qiehaoAdapter
: platform === "bilibili"
? bilibiliAdapter
: genericAdapter,
: platform === "sohuhao"
? sohuhaoAdapter
: platform === "qiehao"
? qiehaoAdapter
: platform === "wangyihao"
? wangyihaoAdapter
: platform === "bilibili"
? bilibiliAdapter
: platform === "juejin"
? juejinAdapter
: platform === "weixin_gzh"
? weixinGzhAdapter
: platform === "zol"
? zolAdapter
: platform === "dongchedi"
? dongchediAdapter
: genericAdapter,
]),
);