dsh-deepseek-web-login 0.6.14 → 0.6.15
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/CHANGELOG.md +25 -0
- package/lib/client.js +32 -73
- package/lib/client.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
本项目遵循大致语义化版本;日期为本地时间。
|
|
4
4
|
|
|
5
|
+
## 0.6.15 — 2026-10-01
|
|
6
|
+
|
|
7
|
+
**界面两处修正(用户反馈):「一键重登」搬到账号库;删掉一堆误导性的"注释"。**
|
|
8
|
+
|
|
9
|
+
用户原话:「首先我没有看到『一键重登』的按钮,其次有很多注释完全不需要,什么 cookie 剩余多少天
|
|
10
|
+
过期,完全没必要显示,不照样还是几个小时就需要重登嘛!这些注释写的真多余,导致界面不美观。」
|
|
11
|
+
|
|
12
|
+
1. **「一键重登」位置错了**:0.6.14 把它 append 到了 `gateCard`(防风控页的设置卡),
|
|
13
|
+
而用户是在「账号库」子标签里找 —— 自然找不到。现在挪到**账号库的按钮行**,紧跟
|
|
14
|
+
「登录新账号(添加)」(两者是同一类动作:弄到可用凭证),按钮文案统一成「一键重登」,
|
|
15
|
+
结果走**全局提示条**(常驻标签栏之上,切子标签也看得见)。
|
|
16
|
+
2. **删掉 cookie 的"还剩多少天"**:原来报的是持久级 cookie 的到期日(实测
|
|
17
|
+
`thumbcache_*` 还剩 399 天),而真正鉴权的 token 只有 **87~370 分钟**寿命 ——
|
|
18
|
+
两个数量级摆在一起只会让人读成"这号还能用 399 天",然后发现几小时就得重登。
|
|
19
|
+
`describeCookieLife` 现在只报构成(`5 项 · 3 会话级 · 2 持久级`),名字与天数都不再出现。
|
|
20
|
+
3. **合并/精简状态行**:「Cookie 过期」并进「Cookie」一行;「凭证来源」去掉长括号;
|
|
21
|
+
「指纹头」/「Cookie 未捕获」的长解释改成短句;删掉信息量为零的「PoW WASM」行。
|
|
22
|
+
4. **账号行元信息瘦身**:从
|
|
23
|
+
`davi***+w5@gmail.com · 9/30 17:34 捕获 · 最近校验 21 小时前 · cookie:5 项 · 3 会话级 · 2 持久级 · .thumbcache_… 还剩 399 天`
|
|
24
|
+
缩到 `9/30 17:34 捕获 · 最近校验 21 小时前`(账号名标题里已经有了,不再重复)。
|
|
25
|
+
|
|
26
|
+
用例:`check-cookie-meta` 改成守新意图(**并且新增一条"不许再出现天数/cookie 名"的牙齿**);
|
|
27
|
+
`check-ui-copy` 新增两条点名守卫 ——「一键重登必须在账号库按钮行里」与「cookie 摘要不许出现天数」,
|
|
28
|
+
两条都做过反向验证(把按钮挪回去 / 把天数加回来 ⇒ 立刻变红)。
|
|
29
|
+
|
|
5
30
|
## 0.6.14 — 2026-09-30
|
|
6
31
|
|
|
7
32
|
**邮箱密码自动重登:「重登」一键点下去就上,另加「一键重登全部」+ 到期前自动续(开关,默认关)。**
|
package/lib/client.js
CHANGED
|
@@ -148,53 +148,18 @@ window.__ModuleLoader__.load({
|
|
|
148
148
|
//#endregion
|
|
149
149
|
//#region src/cookies.ts
|
|
150
150
|
/**
|
|
151
|
-
* 汇总结论。**没有记录时返回 `undefined`**(而不是全 0 的对象)——
|
|
152
|
-
* 调用方要区分"没采到过期信息"(老记录 / 手动粘 token)和"采到了、全是会话级",
|
|
153
|
-
* 这两种情况的界面文案完全不同。
|
|
154
|
-
*/
|
|
155
|
-
function summarizeCookieLife(metas, now = Date.now()) {
|
|
156
|
-
const list = metas ?? [];
|
|
157
|
-
if (list.length === 0) return void 0;
|
|
158
|
-
const persistent = list.filter((item) => !item.session && Number.isFinite(item.expiresAt));
|
|
159
|
-
let latest;
|
|
160
|
-
for (const item of persistent) {
|
|
161
|
-
const expiresAt = item.expiresAt;
|
|
162
|
-
if (!latest || expiresAt > latest.expiresAt) latest = {
|
|
163
|
-
name: item.name,
|
|
164
|
-
expiresAt,
|
|
165
|
-
daysLeft: (expiresAt - now) / 864e5
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
return {
|
|
169
|
-
total: list.length,
|
|
170
|
-
sessionCount: list.length - persistent.length,
|
|
171
|
-
persistentCount: persistent.length,
|
|
172
|
-
...latest ? { latest } : {}
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
/** 剩余时间的口语化写法。 */
|
|
176
|
-
function describeRemaining(daysLeft) {
|
|
177
|
-
if (daysLeft <= 0) return "已过期";
|
|
178
|
-
if (daysLeft >= 1) return `还剩 ${Math.floor(daysLeft)} 天`;
|
|
179
|
-
return `还剩 ${Math.max(1, Math.round(daysLeft * 24))} 小时`;
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
151
|
* 一句话说清 cookie 的寿命构成(界面直接展示)。
|
|
183
152
|
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
153
|
+
* ⚠️ **刻意不报"还剩多少天"**(2026-10-01 由用户反馈删掉):那个数字来自持久级 cookie
|
|
154
|
+
* (实测 `thumbcache_*` 这类还剩 399 天),而**真正鉴权的是 token,寿命只有几小时** ——
|
|
155
|
+
* 两个数量级放在一起只会让人读成"这号还能用 399 天",然后发现几小时就得重登,反而更困惑。
|
|
156
|
+
* 现在只报构成(共几项 / 会话级几个 / 持久级几个),需要更细的信息去看 `/status` 原始字段。
|
|
188
157
|
*/
|
|
189
|
-
function describeCookieLife(summary,
|
|
190
|
-
if (!summary) return "⚠️
|
|
158
|
+
function describeCookieLife(summary, _now = Date.now()) {
|
|
159
|
+
if (!summary) return "⚠️ 未记录";
|
|
191
160
|
const parts = [`${summary.total} 项`];
|
|
192
|
-
|
|
161
|
+
if (summary.sessionCount > 0) parts.push(`${summary.sessionCount} 会话级`);
|
|
193
162
|
if (summary.persistentCount > 0) parts.push(`${summary.persistentCount} 持久级`);
|
|
194
|
-
if (summary.latest) {
|
|
195
|
-
const daysLeft = (summary.latest.expiresAt - now) / 864e5;
|
|
196
|
-
parts.push(`${summary.latest.name} ${describeRemaining(daysLeft)}`);
|
|
197
|
-
}
|
|
198
163
|
return parts.join(" · ");
|
|
199
164
|
}
|
|
200
165
|
//#endregion
|
|
@@ -814,10 +779,30 @@ background:var(--bg2);white-space:pre-wrap;font-size:12px}
|
|
|
814
779
|
const importBtn = el("button", "dsw-btn ghost", "导入备份…");
|
|
815
780
|
const refreshAccountsBtn = el("button", "dsw-btn ghost", "校验全部");
|
|
816
781
|
refreshAccountsBtn.title = "对每个账号做一次只读校验(零额度):刷新登录态、补上账号名、清掉已恢复的失败标记";
|
|
782
|
+
const reloginAllBtn = el("button", "dsw-btn", "一键重登");
|
|
783
|
+
reloginAllBtn.title = "用本机保存的邮箱密码,把所有匹配得到的账号依次自动重登。每个号会起一次无头浏览器(无窗口、跑完即杀),所以是串行的、需要等一会儿。";
|
|
817
784
|
const newGroupBtn = el("button", "dsw-btn ghost", "新建分组");
|
|
818
785
|
newGroupBtn.title = "给账号分类,只影响列表的显示方式 —— 不参与切号、也不影响会话复用与清理";
|
|
819
|
-
accountsIOPanel.append(addAccountBtn, exportBtn, importBtn, refreshAccountsBtn, newGroupBtn);
|
|
786
|
+
accountsIOPanel.append(addAccountBtn, reloginAllBtn, exportBtn, importBtn, refreshAccountsBtn, newGroupBtn);
|
|
820
787
|
accountsCard.append(accountsIOPanel);
|
|
788
|
+
reloginAllBtn.addEventListener("click", () => {
|
|
789
|
+
reloginAllBtn.disabled = true;
|
|
790
|
+
showMessage("正在自动重登(每个号起一次无头浏览器,请稍候)…");
|
|
791
|
+
api("/login/relogin-all", {
|
|
792
|
+
method: "POST",
|
|
793
|
+
body: "{}"
|
|
794
|
+
}).then((result) => {
|
|
795
|
+
const rows = Array.isArray(result?.results) ? result.results : [];
|
|
796
|
+
if (rows.length === 0) {
|
|
797
|
+
showMessage(result?.error ?? "没有可重登的账号", "err");
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
const failed = rows.filter((r) => !r.ok);
|
|
801
|
+
showMessage(`重登完成 ${result?.okCount ?? 0}/${rows.length}` + (failed.length ? `;失败:${failed.map((r) => `${r.display}(${String(r.message ?? "").slice(0, 40)})`).join(" ")}` : `:${rows.map((r) => r.display).join(" ")}`), failed.length ? "" : "ok");
|
|
802
|
+
}).catch((error) => showMessage(`重登失败:${error?.message ?? error}`, "err")).finally(() => {
|
|
803
|
+
reloginAllBtn.disabled = false;
|
|
804
|
+
});
|
|
805
|
+
});
|
|
821
806
|
accountsCard.append(el("p", "dsw-hint", "💡 「登录新账号」会先清掉上次的浏览器登录态(库里已有的账号不受影响),登录后新账号只入库、不切换当前账号 ——加完在列表里点「切换」即可使用。某个账号标着「需要重新登录」时,用它自己那行上的按钮修 ——那条路不清浏览器登录态,能复用就直接复用。导出/导入会弹系统对话框,自己选位置和文件。"));
|
|
822
807
|
const accountsMsg = createMsgNode();
|
|
823
808
|
accountsCard.append(accountsMsg.node);
|
|
@@ -974,11 +959,8 @@ background:var(--bg2);white-space:pre-wrap;font-size:12px}
|
|
|
974
959
|
else if (item.lastCheckError) title.append(el("span", "dsw-badge off", "⚠️ 未能校验(网络)"));
|
|
975
960
|
main.append(title);
|
|
976
961
|
const meta = [];
|
|
977
|
-
if (item.display) meta.push(item.display);
|
|
978
962
|
if (item.capturedAt) meta.push(`${shortTime(item.capturedAt)} 捕获`);
|
|
979
963
|
meta.push(item.lastVerifiedAt ? `最近校验 ${relTime(item.lastVerifiedAt)}` : "尚未校验");
|
|
980
|
-
const cookieMeta = Array.isArray(item.cookieMeta) ? item.cookieMeta : [];
|
|
981
|
-
meta.push(`cookie:${describeCookieLife(summarizeCookieLife(cookieMeta))}`);
|
|
982
964
|
main.append(el("div", "dsw-account-meta", meta.join(" · ")));
|
|
983
965
|
if (item.lastVerifyError) main.append(el("div", "dsw-account-fix", `⚠️ ${relTime(item.lastVerifyError.at)}校验失败(登录态已失效):${item.lastVerifyError.message}`));
|
|
984
966
|
else if (item.lastCheckError) main.append(el("div", "dsw-account-fix", `⚠️ ${relTime(item.lastCheckError.at)}未能校验(网络问题,账号未必失效):${item.lastCheckError.message}`));
|
|
@@ -1478,12 +1460,10 @@ background:var(--bg2);white-space:pre-wrap;font-size:12px}
|
|
|
1478
1460
|
if (loggedIn) {
|
|
1479
1461
|
rows.push(["账号", status.auth.display || "(未获取到账号信息)"]);
|
|
1480
1462
|
rows.push(["捕获时间", status.auth.capturedAt ? new Date(status.auth.capturedAt).toLocaleString() : "未知"]);
|
|
1481
|
-
if (!status.auth.hasCookie && !status.auth.hasFingerprint) rows.push(["凭证来源", "手动粘贴 token
|
|
1482
|
-
else rows.push(["凭证来源", "
|
|
1483
|
-
rows.push(["Cookie", status.auth.hasCookie ?
|
|
1484
|
-
|
|
1485
|
-
rows.push(["指纹头", status.auth.hasFingerprint ? "✅ 已捕获(x-hif-* / x-client-*)" : "未捕获 —— 同上,已实测可用"]);
|
|
1486
|
-
rows.push(["PoW WASM", status.auth.wasmHost || "默认地址"]);
|
|
1463
|
+
if (!status.auth.hasCookie && !status.auth.hasFingerprint) rows.push(["凭证来源", "手动粘贴 token"]);
|
|
1464
|
+
else rows.push(["凭证来源", "浏览器登录捕获"]);
|
|
1465
|
+
rows.push(["Cookie", status.auth.hasCookie ? `✅ 已捕获${status.auth.cookieLife ? ` · ${describeCookieLife(status.auth.cookieLife)}` : ""}` : "未捕获(手动 token 模式本就没有;不影响请求)"]);
|
|
1466
|
+
rows.push(["指纹头", status.auth.hasFingerprint ? "✅ 已捕获" : "未捕获(不影响请求)"]);
|
|
1487
1467
|
rows.push(["token 长度", `${status.auth.tokenLength ?? 0} 字符`]);
|
|
1488
1468
|
if (status.validation) rows.push(["服务端校验", status.validation.ok ? "通过" : `失败:${status.validation.error ?? ""}`]);
|
|
1489
1469
|
const verifiedAt = status.auth?.lastVerifiedAt;
|
|
@@ -1781,27 +1761,6 @@ background:var(--bg2);white-space:pre-wrap;font-size:12px}
|
|
|
1781
1761
|
});
|
|
1782
1762
|
cleanupNowRow.append(cleanupNowBtn, cleanupNowHint);
|
|
1783
1763
|
gateCard.append(cleanupNowRow);
|
|
1784
|
-
const reloginAllRow = el("div", "dsw-gate-row");
|
|
1785
|
-
reloginAllRow.append(el("span", "dsw-gate-label", "一键重登"));
|
|
1786
|
-
const reloginAllBtn = el("button", "dsw-btn ghost", "用存的密码重登全部");
|
|
1787
|
-
const reloginAllHint = el("span", "dsw-hint", "");
|
|
1788
|
-
reloginAllBtn.addEventListener("click", () => {
|
|
1789
|
-
reloginAllBtn.disabled = true;
|
|
1790
|
-
reloginAllHint.textContent = "正在自动重登(每个号起一次无头浏览器,请稍候)…";
|
|
1791
|
-
api("/login/relogin-all", {
|
|
1792
|
-
method: "POST",
|
|
1793
|
-
body: "{}"
|
|
1794
|
-
}).then((result) => {
|
|
1795
|
-
const rows = Array.isArray(result?.results) ? result.results : [];
|
|
1796
|
-
reloginAllHint.textContent = rows.length ? `完成 ${result?.okCount ?? 0}/${rows.length}:` + rows.map((r) => `${r.ok ? "✅" : "❌"}${String(r.display ?? "").slice(0, 20)}`).join(" ") : result?.error ?? "没有可重登的账号";
|
|
1797
|
-
}).catch((error) => {
|
|
1798
|
-
reloginAllHint.textContent = `重登失败:${error?.message ?? error}`;
|
|
1799
|
-
}).finally(() => {
|
|
1800
|
-
reloginAllBtn.disabled = false;
|
|
1801
|
-
});
|
|
1802
|
-
});
|
|
1803
|
-
reloginAllRow.append(reloginAllBtn, reloginAllHint);
|
|
1804
|
-
gateCard.append(reloginAllRow);
|
|
1805
1764
|
const autoReloginRow = el("div", "dsw-gate-row");
|
|
1806
1765
|
const autoReloginLabel = el("label", "dsw-switch");
|
|
1807
1766
|
const autoReloginInput = el("input");
|