У меня есть скрипт Greasemonkey, который настраивает некоторые элементы Twitch.tv в соответствии с шепотом сообщений от чат-бота на определенном канале twitch. Моя цель — наблюдать за шепотом, читать каждое новое сообщение шепота, вносить соответствующие коррективы и после этого закрывать окно чата, чтобы я не видел, что получил шепот.
Я не так хорошо знаком с Greasemonkey, HMTL или Javascript в целом. Единственный известный мне способ сделать это — использовать observeDOM
в классе, содержащем все окна шепота (conversation-manager
):
// 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();
}
}
У меня все еще есть проблемы, что читаются только некоторые сообщения шепотом или вообще не читаются. В чем может быть проблема с моим подходом?