dsh-douyin-mac 0.1.10 → 0.1.11

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 CHANGED
@@ -1,5 +1,10 @@
1
1
  # 更新记录
2
2
 
3
+ ## 0.1.11(2026-11-05)
4
+
5
+ - 登录后自动关闭“是否保存登录信息”弹层(选择取消,不保存密码),避免它挡住消息列表导致读取联系人为 0。
6
+ - 好友互动读取到空消息列表时给出明确提示:当前抖音没有会话,需先在网页版打开“消息”或让好友先发消息。
7
+
3
8
  ## 0.1.10(2026-11-05)
4
9
 
5
10
  - 自检插件版本改为读取 `package.json`,不再固定显示上游 1.4.6。
package/chat-browser.mjs CHANGED
@@ -974,6 +974,14 @@ export class ChatBrowser {
974
974
  listContacts({ signal, verifyFollowing = this.following === null, backgroundOnly = false } = {}) {
975
975
  return this.withPage(async page => {
976
976
  if (backgroundOnly && await this.isForeground(page)) throw Object.assign(new Error('专用浏览器在前台,暂不切换私信页。'), { code: 'CHAT_FOREGROUND' });
977
+ // 登录后的“是否保存登录信息”弹层会挡住消息列表,先取消它。
978
+ await page.evaluate(() => {
979
+ if (!/是否保存登录信息/.test(document.body.innerText || '')) return false;
980
+ const usable = element => { const box = element.getBoundingClientRect(), style = getComputedStyle(element); return box.width > 0 && box.height > 0 && style.display !== 'none' && style.visibility !== 'hidden'; };
981
+ const cancel = [...document.querySelectorAll('button,div,span')].find(element => usable(element) && (element.innerText || '').trim() === '取消');
982
+ if (!cancel) return false;
983
+ cancel.click(); return true;
984
+ }).catch(() => false);
977
985
  const initial = await this.dialog(page, signal, { open: !backgroundOnly });
978
986
  if (initial.blocked) return { ...initial, contacts: [] };
979
987
  if (verifyFollowing && !backgroundOnly) {
package/client.js CHANGED
@@ -232,6 +232,7 @@ window.__ModuleLoader__.load({
232
232
  state?.interactions?.friend?.waitReason && h('div', { style: row }, h(Button, { type: 'button', size: 'sm', variant: 'outline', disabled: !ready || busy.has('chatPrepare') || state.interactions.friend.canPrepare === false, onClick: () => { void perform('chatPrepare', () => api.request('/chat/prepare', {})); } }, busy.has('chatPrepare') || state.interactions.friend.preparing ? '正在准备…' : '准备回复通道/重新连接并重试')),
233
233
  button('读取联系人与群聊', 'chatList', () => { void perform('chatList', async () => { const result = await api.request('/chat/contacts', {}); if (result.blocked || result.loginRequired || result.verificationRequired || !Array.isArray(result.contacts)) throw new Error('请在专用浏览器完成登录或验证。'); setContacts(result.contacts); setDiscovery(result.listDiscovery || null); return result; }); }, chat.status.kind === 'saving'),
234
234
  note('读取范围是抖音网页版当前会话,不代表全部关注好友或所有群。要授权群聊,请先让群会话出现在抖音消息列表,再刷新。'), contacts && note(`本次读取:个人 ${contacts.filter(item => item.isGroup === false).length} 个 · 群聊 ${contacts.filter(item => item.isGroup === true).length} 个。${discovery?.scannedToEnd === false ? ` 当前列表尚未完整读取。${discovery.reason || ''}` : ''}`),
235
+ contacts && contacts.length === 0 && note('抖音消息列表目前是空的(页面显示“暂无会话”),所以没有可授权的个人会话或群聊;先在抖音网页版打开“消息”,或让好友先发一条消息,再点“读取联系人与群聊”。'),
235
236
  contacts?.some(item => item.relationshipStatus === 'unavailable' || item.isGroup === true || typeof item.isGroup !== 'boolean') && toggle('授权已核对的现有会话', chat.draft.allowConversationOnly, value => { existingAuthorization.current = value; chat.edit({ allowConversationOnly: value, ...(!value ? { recipientIds: chat.draft.recipientIds.filter(id => shownContacts.some(item => item.id === id && item.followed === true && item.isGroup === false)) } : {}) }, value ? { blurOnly: true } : { immediate: true }); }),
236
237
  ...[false, true, null].flatMap(kind => { const items = shownContacts.filter(item => item.isGroup === kind || kind === null && typeof item.isGroup !== 'boolean'); return items.length ? [note(kind === false ? '个人会话' : kind === true ? '群聊(仅被 @ 或叫到响应昵称时回复)' : '旧记录类型待核对(暂不可选)'), ...items.map(item => h('label', { key: item.id, style: row }, h('input', { type: 'checkbox', 'aria-label': `许可联系人 ${item.name || item.displayName || '联系人'}`, checked: chat.draft.recipientIds.includes(item.id), disabled: !ready || !chat.draft.recipientIds.includes(item.id) && (item.notListed || !(item.followed === true && item.isGroup === false || chat.draft.allowConversationOnly === true && typeof item.isGroup === 'boolean')), onChange: event => chat.edit({ recipientIds: event.target.checked ? [...chat.draft.recipientIds, item.id] : chat.draft.recipientIds.filter(id => id !== item.id) }, { immediate: true }) }), item.name || item.displayName || '许可会话'))] : []; }),
237
238
  area('群聊响应昵称(逗号或换行分隔)', chat, 'groupMentionNamesText', 2, true), status(chat), note(`今日回复模型请求 ${state?.chat?.daily?.requests || 0} 次 · 今日分享 ${state?.share?.daily?.attempts || 0} 次。未确认发送会暂停,不自动重发。`), ...(state?.chat?.contacts || []).filter(item => item.identityReviewRequired === true || item.recovery?.requiresUserAction === true || /登录|验证码|未授权|许可.*(?:不足|失效|撤销)|身份.*(?:变化|不一致|未通过|不明|不足)/.test(item.reason || '') || ['paused', 'delivery-uncertain'].includes(item.status) && !(item.recovery?.autoPendingCount > 0 || item.recovery?.autoRetryCount > 0)).map(item => h('div', { key: item.id }, note(item.reason || '该会话暂缓处理,状态会继续更新。'), item.identityReviewRequired === true && note('请重新读取联系人并确认许可名单;身份未通过前不会发送。'))), ...(state?.share?.unavailableRecipients || []).map(item => note(`暂不能自主分享:${item.name || '许可会话'} · ${item.reason}`)), ...reviewList('share'), h('details', null, h('summary', null, '回复处理记录'), h('pre', { style: { whiteSpace: 'pre-wrap' } }, JSON.stringify({ recovery: state?.chat?.recovery, contacts: (state?.chat?.contacts || []).map(item => ({ id: item.id, status: item.status, reason: item.reason, recovery: item.recovery, pending: Boolean(item.pending), unanswered: item.unanswered?.length || 0 })), events: state?.chat?.events || [] }, null, 2))), h('details', null, h('summary', null, '最近分享记录'), ...(state?.share?.recent || []).slice().reverse().map(item => h('div', { key: item.operationId }, note(`作品 ${item.videoId} · ${state?.share?.inProgress && state.share.activity?.operationId === item.operationId ? '正在分享' : ({ confirmed: '已确认送达', 'not-sent': '未发出', uncertain: '送达未确认', reserved: '已预留,待核对', clicking: '处理中,待核对', 'resolved-confirmed': '人工已确认送达', 'resolved-not-sent': '人工已确认未送达' }[item.status] || item.status)}`), shareFailureMessage(item) && note(`原因:${shareFailureMessage(item)}`))))),
package/core.mjs CHANGED
@@ -586,7 +586,20 @@ export class BrowserController {
586
586
  : loggedIn === false ? '未检测到抖音登录态,点“打开登录页”扫码登录。' : '无法确认登录态;可点“打开登录页”刷新后重试。';
587
587
  return { connected: true, pageOpen: true, loggedIn, pageShowsLogin, loginRequired, verificationRequired, url: page.url(), title: state.title || '', note, at: Date.now() };
588
588
  }
589
+ // 登录成功后抖音会弹“是否保存登录信息”,会挡住消息面板;这里选择“取消”避免保存密码。
590
+ async _dismissLoginPrompt(page) {
591
+ try {
592
+ return await page.evaluate(() => {
593
+ if (!/是否保存登录信息/.test(document.body.innerText || '')) return false;
594
+ const usable = element => { const box = element.getBoundingClientRect(), style = getComputedStyle(element); return box.width > 0 && box.height > 0 && style.display !== 'none' && style.visibility !== 'hidden'; };
595
+ const cancel = [...document.querySelectorAll('button,div,span')].find(element => usable(element) && (element.innerText || '').trim() === '取消');
596
+ if (!cancel) return false;
597
+ cancel.click(); return true;
598
+ }).catch(() => false);
599
+ } catch { return false; }
600
+ }
589
601
  async _bringPageToFront(page) {
602
+ await this._dismissLoginPrompt(page);
590
603
  try {
591
604
  const session = await page.context().newCDPSession(page);
592
605
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-douyin-mac",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "type": "module",
5
5
  "description": "macOS 版 DSH 抖音工具:Chrome 专用窗口驱动、人格记忆与自主观看",
6
6
  "license": "MIT",