Greasy Fork is available in English.
파트너 스트리머이며 매니저가 아닌 채팅의 닉네임과 메시지를 연두색으로 표시. 닉네임이 너무 어두운 경우 색상 제거 (시인성 개선)
当前为
// ==UserScript==
// @name Chzzk_Live: Partner_Not_Manager Green+BlackNicknameDelete
// @namespace Chzzk_Live: Partner_Not_Manager Green
// @version 1.1
// @description 파트너 스트리머이며 매니저가 아닌 채팅의 닉네임과 메시지를 연두색으로 표시. 닉네임이 너무 어두운 경우 색상 제거 (시인성 개선)
// @author DOGJIP
// @match https://chzzk.naver.com/*
// @grant none
// @run-at document-end
// @license MIT
// ==/UserScript==
(function() {
'use strict';
const LIGHT_GREEN = "rgb(102,255,102)";
let chatObserver = null;
function cleanNicknameStyle(elem) {
const computedColor = getComputedStyle(elem).color;
const rgb = computedColor.match(/\d+/g);
if (!rgb) return;
const [r, g, b] = rgb.map(Number);
const isTooDark = (r < 40 && g < 40 && b < 40);
const isTransparent = computedColor.includes('rgba') && computedColor.includes(', 0)');
if (isTooDark || isTransparent) {
elem.style.removeProperty('color');
}
}
function processChatMessage(messageElem) {
if (messageElem.getAttribute('data-partner-processed') === 'true') return;
const isPartner = messageElem.querySelector('[class*="name_icon__zdbVH"]') !== null;
const badgeImgs = messageElem.querySelectorAll('.badge_container__a64XB img');
let isManager = false;
badgeImgs.forEach(img => {
if (img.src.includes("manager.png")) {
isManager = true;
}
});
const nicknameElem = messageElem.querySelector('.live_chatting_username_nickname__dDbbj');
const textElem = messageElem.querySelector('.live_chatting_message_text__DyleH');
// 모든 닉네임에 대해 스타일 정리
if (nicknameElem) {
cleanNicknameStyle(nicknameElem);
}
if (isPartner && !isManager) {
if (nicknameElem) nicknameElem.style.color = LIGHT_GREEN;
if (textElem) textElem.style.color = LIGHT_GREEN;
}
messageElem.setAttribute('data-partner-processed', 'true');
}
function setupChatObserver() {
if (chatObserver) {
chatObserver.disconnect();
}
const chatContainer = document.querySelector('[class*="live_chatting_list_wrapper__"]');
if (!chatContainer) {
setTimeout(setupChatObserver, 500);
return;
}
const existingMessages = chatContainer.querySelectorAll('[class^="live_chatting_message_chatting_message__"]');
existingMessages.forEach(msg => processChatMessage(msg));
chatObserver = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === 1) {
if (node.className && node.className.indexOf('live_chatting_message_chatting_message__') !== -1) {
processChatMessage(node);
} else {
const msgs = node.querySelectorAll('[class^="live_chatting_message_chatting_message__"]');
msgs.forEach(msg => processChatMessage(msg));
}
}
});
});
});
chatObserver.observe(chatContainer, { childList: true, subtree: true });
}
function setupSPADetection() {
let lastUrl = location.href;
function onUrlChange() {
if (location.href !== lastUrl) {
lastUrl = location.href;
setTimeout(setupChatObserver, 1000);
}
}
const origPushState = history.pushState;
history.pushState = function() {
origPushState.apply(history, arguments);
onUrlChange();
};
const origReplaceState = history.replaceState;
history.replaceState = function() {
origReplaceState.apply(history, arguments);
onUrlChange();
};
window.addEventListener('popstate', onUrlChange);
}
function init() {
setupChatObserver();
setupSPADetection();
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();