You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Telegram网页端控制台JS标记消息已读的技术求助

Telegram网页端控制台JS标记消息已读的技术求助

兄弟我太懂你这个痛点了!之前做类似的Telegram网页端消息抓取工具时,也被这个“未读消息锁死滚动+不加载新DOM”的坑折腾过好一阵。

先给你理清楚核心问题:Telegram网页端的逻辑是只要聊天里存在未读消息,它就会强制把视图拉回未读消息的位置,而且不会加载更旧的历史消息——你的滚动函数只是单纯把列表滚到底,但完全没触发Telegram内部的“标记消息为已读”的逻辑,所以系统一直认为还有未读消息,自然不会给你加载新的DOM元素。

下面给你几个亲测有效的解决方案,直接在控制台里就能用:

方案1:模拟用户操作触发已读标记(最稳定,不易失效)

这个方法是模拟用户点击未读标记、触发滚动事件的真实操作,Telegram的前端会识别这个行为并标记消息为已读。

先写一个标记已读的辅助函数,再和你的滚动逻辑结合:

// 标记所有未读消息为已读
function markAllMessagesAsRead() {
  // 匹配Telegram网页端未读消息的标记元素(类名可能随版本微调,可自行在控制台用document.querySelectorAll验证)
  const unreadElements = document.querySelectorAll('.Message.unread, .UnreadBadge, .MessageList-unreadMarker');
  
  unreadElements.forEach(el => {
    // 模拟鼠标点击事件,触发Telegram的已读逻辑
    el.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }));
    // 额外触发focus事件,确保Telegram捕捉到状态变化
    el.dispatchEvent(new FocusEvent('focus', { bubbles: true }));
  });

  // 给聊天容器再触发一次scroll事件,让系统确认所有消息已可见
  const chatContainer = document.querySelector('.ChatContainer');
  if (chatContainer) {
    chatContainer.dispatchEvent(new Event('scroll', { bubbles: true }));
  }
}

// 滚动到底部并标记已读的组合函数
function scrollToBottomAndMarkRead() {
  const messageList = document.querySelector('.MessageList');
  if (!messageList) return;

  // 先滚动到底部
  messageList.scrollTop = messageList.scrollHeight;
  // 标记已读
  markAllMessagesAsRead();
  // 延迟500ms再滚一次,等待Telegram加载新的历史消息(DOM更新是异步的)
  setTimeout(() => {
    messageList.scrollTop = messageList.scrollHeight;
  }, 500);
}

你只需要在控制台里运行scrollToBottomAndMarkRead(),代替原来的scrollChatToBottom()就行。如果发现类名不对,直接用控制台的元素选择器工具,找未读消息对应的类名替换就行。

方案2:调用Telegram内部的已读方法(更直接,但可能随版本失效)

Telegram网页端是基于React开发的,内部有状态管理的store,里面有直接标记已读的方法。你可以尝试在控制台里调用这个内部方法:

// 尝试找到并调用Telegram内部的标记已读方法
function callInternalMarkAsRead() {
  // 遍历React DevTools暴露的内部store,找到带markAsRead方法的实例
  if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
    const renderers = window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers;
    if (renderers.length > 0) {
      const stores = Object.values(renderers[0].internalStore);
      for (const store of stores) {
        if (typeof store.markAsRead === 'function') {
          store.markAsRead();
          console.log('已调用内部方法标记为已读');
          break;
        }
      }
    }
  }
}

这个方法更直接,但要注意:Telegram的前端版本更新后,内部store的结构可能会变,导致这个方法失效,所以优先用方案1。

额外提醒

  • 如果滚动后还是没加载新消息,可以把setTimeout的延迟时间调长一点(比如1000ms),给Telegram的DOM更新留足时间
  • 不要太频繁调用这个函数,避免触发Telegram的反爬限制(毕竟是网页端,太频繁的自动化操作可能会被临时限制)

备注:内容来源于stack exchange,提问作者struggleendlessly

火山引擎 最新活动