6218d6bad1
update names based on the element from the mutation event rather than checking the chatbox for unchecked messages each mutation
232 lines
6.7 KiB
TypeScript
232 lines
6.7 KiB
TypeScript
import { obfuscator } from './obfuscator'
|
|
import { NameConfigInstance, nameImages, usernameExtraSuffix } from './options'
|
|
import { ChatMessage, elementTreeFind, innermostElement } from './util'
|
|
|
|
function loadChatMessage(chatboxMessage: Element) {
|
|
// only chat messages
|
|
const chatboxMessageInner = chatboxMessage.querySelector(
|
|
'.chat-line__message'
|
|
)
|
|
if (!chatboxMessageInner) {
|
|
return
|
|
}
|
|
|
|
// get chatbox details
|
|
const chatboxBadgeContainer = chatboxMessage.querySelector<HTMLSpanElement>(
|
|
'.chat-line__message--badges'
|
|
)
|
|
|
|
const chatboxUser = chatboxMessage.querySelector<HTMLSpanElement>(
|
|
'.chat-line__username'
|
|
)
|
|
if (!chatboxUser) {
|
|
console.error("found message, couldn't find user")
|
|
return
|
|
}
|
|
|
|
// already applied username
|
|
if (chatboxUser.querySelector('.obf-name')) {
|
|
return
|
|
}
|
|
|
|
const chatboxUserInner = chatboxUser.querySelector<HTMLSpanElement>(
|
|
'.chat-author__display-name'
|
|
)
|
|
if (!chatboxUserInner) {
|
|
console.error("found message, couldn't find userInner")
|
|
return
|
|
}
|
|
|
|
// check if mod
|
|
let isMod = false
|
|
if (chatboxBadgeContainer) {
|
|
for (const badge of chatboxBadgeContainer.children) {
|
|
if (
|
|
badge.hasAttribute('data-badge') &&
|
|
(badge.getAttribute('data-badge') === 'moderator' ||
|
|
badge.getAttribute('data-badge') === 'broadcaster')
|
|
) {
|
|
isMod = true
|
|
chatboxMessage.classList.add('ismod')
|
|
}
|
|
}
|
|
}
|
|
|
|
// combine details into object
|
|
const chatMessage: ChatMessage = {
|
|
username: chatboxUserInner.textContent,
|
|
isMod,
|
|
}
|
|
|
|
// run main script (process chatMessage), return new ChatMessage
|
|
const newChatMessage = obfuscator(chatMessage)
|
|
|
|
if (newChatMessage !== null) {
|
|
setUsernameDetails(newChatMessage, chatboxUserInner, true)
|
|
}
|
|
|
|
loadReplyLine(chatboxMessage)
|
|
loadMessageMentions(chatboxMessage)
|
|
}
|
|
|
|
function loadReplyLine(chatboxMessage: Element) {
|
|
const replyline = chatboxMessage.querySelector('.ffz--fix-reply-line')
|
|
const replyUsername = replyline?.querySelector<HTMLElement>(
|
|
'p > span:nth-child(1)'
|
|
)
|
|
|
|
if (!replyUsername) {
|
|
return
|
|
}
|
|
|
|
// already applied username
|
|
if (replyUsername.querySelector('.obf-name')) {
|
|
return
|
|
}
|
|
|
|
const chatMessage: ChatMessage = {
|
|
username: replyUsername.textContent.replace(/^@/, ''),
|
|
isMod: false,
|
|
}
|
|
|
|
// run main script (process chatMessage), return new ChatMessage
|
|
const newChatMessage = obfuscator(chatMessage)
|
|
|
|
if (newChatMessage !== null) {
|
|
setUsernameDetails(newChatMessage, replyUsername, false, '@')
|
|
}
|
|
}
|
|
|
|
function loadMessageMentions(chatboxMessage: Element) {
|
|
function eachMention(messageMention: HTMLElement) {
|
|
// already applied username
|
|
if (messageMention.querySelector('.obf-name')) {
|
|
return
|
|
}
|
|
|
|
const chatMessage: ChatMessage = {
|
|
username: messageMention.textContent.replace(/^@/, ''),
|
|
isMod: false,
|
|
}
|
|
|
|
// run main script (process chatMessage), return new ChatMessage
|
|
const newChatMessage = obfuscator(chatMessage)
|
|
|
|
if (newChatMessage !== null) {
|
|
setUsernameDetails(newChatMessage, messageMention, false, '@')
|
|
}
|
|
}
|
|
|
|
const messageMentions = chatboxMessage.querySelectorAll<HTMLElement>(
|
|
'.chat-line__message-mention'
|
|
)
|
|
|
|
for (const messageMention of messageMentions) {
|
|
eachMention(messageMention)
|
|
}
|
|
}
|
|
|
|
function loadAdditionalUserNames(chatboxMessage: Element) {
|
|
// look for additional chat member names
|
|
const chatterNames =
|
|
chatboxMessage.querySelectorAll<HTMLElement>('.chatter-name')
|
|
|
|
for (const chatterName of chatterNames) {
|
|
const chatterNameBox = innermostElement<HTMLElement, HTMLElement>(
|
|
chatterName
|
|
)
|
|
|
|
// already applied username
|
|
if (chatterNameBox.querySelector('.obf-name')) {
|
|
continue
|
|
}
|
|
|
|
const username = chatterNameBox.textContent
|
|
if (!username) {
|
|
continue
|
|
}
|
|
|
|
// combine details into object
|
|
const chatMessage: ChatMessage = {
|
|
username,
|
|
isMod: false,
|
|
}
|
|
|
|
// run main script (process chatMessage), return new ChatMessage
|
|
const newChatMessage = obfuscator(chatMessage)
|
|
|
|
if (newChatMessage !== null) {
|
|
setUsernameDetails(newChatMessage, chatterNameBox)
|
|
}
|
|
}
|
|
}
|
|
|
|
function setUsernameDetails(
|
|
newChatMessage: NameConfigInstance,
|
|
usernamebox: HTMLElement,
|
|
doColor = false,
|
|
prefix: string = ''
|
|
) {
|
|
const suffix = usernameExtraSuffix(newChatMessage)
|
|
const username = `${newChatMessage.username}${suffix}`
|
|
|
|
const container = document.createElement('span')
|
|
container.classList.add('obf-name')
|
|
|
|
const imageName = newChatMessage.image
|
|
if (imageName) {
|
|
// image name
|
|
const image = nameImages[imageName]
|
|
|
|
const imgElem = document.createElement('img')
|
|
imgElem.classList.add('obf-image', 'ffz--pointer-events', 'ffz-tooltip')
|
|
imgElem.setAttribute('data-tooltip-type', 'html')
|
|
imgElem.setAttribute('data-title', username)
|
|
imgElem.setAttribute('alt', username)
|
|
imgElem.setAttribute('src', image)
|
|
|
|
const prefixElem = document.createElement('span')
|
|
prefixElem.textContent = prefix
|
|
|
|
const suffixElem = document.createElement('span')
|
|
suffixElem.textContent = suffix
|
|
|
|
container.replaceChildren(prefixElem, imgElem, suffixElem)
|
|
} else {
|
|
// text name only
|
|
container.textContent = `${prefix}${username}`
|
|
}
|
|
|
|
if (doColor) {
|
|
container.style.color = newChatMessage.color
|
|
}
|
|
|
|
usernamebox.replaceChildren(container)
|
|
}
|
|
|
|
export function eachMutation(record: MutationRecord) {
|
|
const target = record.target as HTMLElement
|
|
if (target.classList.contains('chat-scrollable-area__message-container')) {
|
|
for (const target of record.addedNodes) {
|
|
eachMutationTarget(record, target as HTMLElement)
|
|
}
|
|
} else {
|
|
eachMutationTarget(record, record.target as HTMLElement)
|
|
}
|
|
}
|
|
|
|
function eachMutationTarget(record: MutationRecord, target: HTMLElement) {
|
|
const chatboxMessage = elementTreeFind<HTMLElement, HTMLElement>(
|
|
target,
|
|
elem =>
|
|
elem.parentElement?.classList.contains(
|
|
'chat-scrollable-area__message-container'
|
|
) || false
|
|
)
|
|
if (chatboxMessage) {
|
|
console.warn('[OBFUSCATOR] mutated message', chatboxMessage, record)
|
|
loadChatMessage(chatboxMessage)
|
|
loadAdditionalUserNames(chatboxMessage)
|
|
}
|
|
}
|