阅读抽搐耳语消息与油脂猴

Reading Twitch Whisper Messages with Greasemonkey

本文关键字:油脂 消息 耳语 抽搐      更新时间:2023-09-26

我有一个 greasemonkey 脚本,可以根据特定 twitch 频道上聊天机器人的耳语消息调整 Twitch.tv 的某些元素。我的目标是观察耳语聊天,阅读每条新的鞭打消息,相应地进行一些调整,然后关闭聊天窗口,这样我就不会看到我收到了窃窃私语。

我对Greasemonkey,HMTL或Javascript不太熟悉。我知道这样做的唯一方法是在包含所有耳语窗口(conversation-manager)的类上使用observeDOM

  // Observe twitch whisper chat
  var whisperArea = document.getElementsByClassName('conversations-manager')[0];
  observeDOM( whisperArea ,function(){ 
    NewWhisperMessage();
  });

据我所知,观察确实可靠。现在到没有的部分:我的方法NewWhisperMessage自己。

首先,我想描述一下我的第一个方法。一开始,我试图找到所有新的耳语。收到耳语后,耳语窗口将打开。耳语窗口本身具有多条消息行,如下所示:

<div class="ember-view conversation-chat-line incoming" title="Sat Jul 09 2016 11:52:38 GMT+0200" id="ember2564">
<span style="" class="from">NameOfMessageWriter</span>
<span class="colon">:</span>
<span style="" class="message">
        Here is the message!
      </span>
</div>

一般来说,此时我只会把类的最后一个元素conversation-chat-line

var allChatMessages = document.getElementsByClassName("conversation-chat-line");
var newestChatMessage = allChatMessages[allChatMessages.length - 1];

这有时有效,但有点不可靠,因为似乎有时会在一个 DOM 更新中到达多个消息(这有意义吗?当我注意到这一点时,我想出了一个更复杂的想法,它工作更可靠,但似乎仍然经常失败。

我的方法大致分为 4 个步骤:

1)如果这是本会话的第一个新耳语(LastWhisperTitle仍然是空的),那么必须找到一个起点。为此,我尝试在 twitch 聊天窗口中找到分隔符元素,以获取新的耳语消息(第 new-message-divider 类。从那里开始,我尝试在此之前获取聊天消息,并存储title属性和此消息的消息文本以唯一标识消息(我不能使用 id 属性,因为它在耳语窗口关闭并重新打开时会发生变化)。此步骤仅执行一次。

2)现在我向后迭代所有聊天消息,直到到达由两个变量(标题和消息文本)标识的最后一个消息。要获取所有聊天消息,我使用getElementsByClassName.我存储此最新消息的索引并从步骤 3) 开始)。

3)有了第一个新聊天消息的索引,我开始向前迭代并按顺序解析每条消息。

4) 阅读新消息时关闭耳语窗口。(条件仅允许在没有新消息到达时手动打开耳语窗口)

这是最后的梅托德:

var LastWhisperTitle = "";
var LastWhisperMessage = "";
var ChannelName = "NameOfChatBot"
function NewWhisperMessage(){
    if(LastWhisperTitle == "") {
        // New Session: Find first new whisper
        // Find new message divider
        var newMessageDividerArray = document.getElementsByClassName("new-message-divider");
        var newMessageDivider = newMessageDividerArray[newMessageDividerArray.length - 1];
        // Find newest message already read
        var sibling = newMessageDivider.previousSibling;
        while(sibling) {
            if(sibling.nodeType == 1) {
                if(sibling.className != "undefined"){
                    if(sibling.className.indexOf("conversation-chat-line") > -1) {
                        break;
                    }
                }
            }
            sibling = sibling.previousSibling;
        }
        if(!sibling){
            return;
        }
        // Store this message as last read whisper
        LastWhisperTitle = sibling.title;
        LastWhisperMessage = sibling.getElementsByClassName("message")[0].textContent.trim();
    }
    // Get all messages
    var whisperMessageArray = document.getElementsByClassName("conversation-chat-line");
    var foundNewMessage = false;
    // Find index in array of the first new message
    var firstNewMessageIndex = 0;
    for(i = whisperMessageArray.length - 1; i >= 0; i--){
        var currentWhisper = whisperMessageArray[i];
        var currentTitle = currentWhisper.title;
        var currentMessage = currentWhisper.getElementsByClassName("message")[0].textContent.trim()
        if(currentTitle == LastWhisperTitle && currentMessage == LastWhisperMessage){
            // This message was already read -> the message with the previous index is new
            if(i == whisperMessageArray.length - 1) {
                // No new message
                return;
            } else {
                firstNewMessageIndex = i+1;
                break;
            }
        }
    }   
    if(firstNewMessageIndex == 0){
        // No new message
        return;
    }
    // Parse all messages from index to newest message
    for( i = firstNewMessageIndex; i < whisperMessageArray.length; i++){
        var currentWhisper = whisperMessageArray[i];
        var writer = currentWhisper.getElementsByClassName("from")[0].textContent;
        var message = currentWhisper.getElementsByClassName("message")[0].textContent.trim();
        if(writer == ChannelName){
            ParseWhisperMessage(message);
            foundNewMessage = true;
        }
        LastWhisperTitle = currentWhisper.title;
        LastWhisperMessage = message;
    }
    if(foundNewMessage){
        // Close Chat Window
        CloseWhisperWindow();
    }
}

我仍然遇到问题,只阅读一些或根本没有耳语消息。我的方法可能有什么问题?

我似乎发现了问题。我的方法本身基本上有效,唯一的问题是当打开多个耳语对话时,一切都变得有问题,因为我在整个document上使用document.getElementsByClassName("conversation-chat-line");,这也将从其他用户(不仅是抽搐机器人)的对话中获取消息。这搞砸了LastWhisperTitleLastWhisperMessage的价值观.

解决方案是将这段代码放在我的函数的开头:

var conversationHeaderNames = document.getElementsByClassName('conversation-header-name');
var currentConversation;
// Find the correct conversation window
for(i = 0; i < conversationHeaderNames.length; i++){
    if(conversationHeaderNames[i].innerHTML.trim() == ChannelName){
        currentConversation = conversationHeaderNames[i].parentNode.parentNode;
        break;
    }
}
if(!currentConversation) return; // No conversation with chat bot

然后我只需要用currentConversation替换document就可以了。