Greasy Fork

Greasy Fork is available in English.

Chzzk_Live: Partner_Not_Manager Green+BlackNicknameDelete

파트너 스트리머이며 매니저가 아닌 채팅의 닉네임과 메시지를 연두색으로 표시. 닉네임이 너무 어두운 경우 색상 제거 (시인성 개선)

目前为 2025-04-07 提交的版本。查看 最新版本

作者
DOGJIP
评分
0 0 0
版本
1.1
创建于
2025-04-07
更新于
2025-04-07
大小
4.5 KB
许可证
MIT
适用于

파트너 스트리머이면서 매니저가 아닌 채팅의 닉네임과 메시지를 연두색으로 표시함
일반 채팅들 사이에 채팅을 보기 더 쉬워집니다 + 기존 닉네임에서 검은색등으로 숨는 닉네임이 보이도록 패치합니다
다만 테스트 조건이 보기 어려워 아래의 테스트 코드를 통해 정상작동을 확인 했으나, 파트너 스트리머이면서 매니저가 아닌 채팅의 적용은 확인하지 못했습니다.
// ==UserScript==
// @name Chzzk_Test: Fan Badge Green
// @namespace Chzzk_Test: Fan Badge Green
// @version 1.0
// @description 테스트용: 후원뱃지가 있으면서 매니저가 아닌 유저의 닉네임과 메시지를 초록색으로 표시
// @author DOGJIP
// @match https://chzzk.naver.com/*
// @grant none
// @run-at document-end
// @license MIT
// ==/UserScript==

(function() {
'use strict';

const GREEN_COLOR = "rgb(102,200,102)";
let chatObserver = null;

// 채팅 메시지에 대해 후원뱃지(fan_03.png) 조건 확인 및 스타일 적용
function processChatMessage(messageElem) {
// 이미 처리된 메시지 건너뛰기
if (messageElem.getAttribute('data-fan-processed') === 'true') return;

// 배지 이미지들을 찾아서 조건 체크 (후원뱃지와 매니저 여부)
const badgeImgs = messageElem.querySelectorAll('.badge_container__a64XB img');
let isFan = false, isManager = false;
badgeImgs.forEach(img => {
if (img.src.includes("fan_03.png")) isFan = true;
if (img.src.includes("manager.png")) isManager = true;
});

// 조건에 맞으면 닉네임과 메시지에 초록색 인라인 스타일 적용
if (isFan && !isManager) {
const nicknameElem = messageElem.querySelector('.live_chatting_username_nickname__dDbbj');
const textElem = messageElem.querySelector('.live_chatting_message_text__DyleH');
if (nicknameElem) nicknameElem.style.color = GREEN_COLOR;
if (textElem) textElem.style.color = GREEN_COLOR;
}

// 중복 적용 방지
messageElem.setAttribute('data-fan-processed', 'true');
}

// 채팅 컨테이너를 감시하는 옵저버 설정 (새 채팅 메시지가 추가될 때마다 처리)
function setupChatObserver() {
// 기존 옵저버 해제
if (chatObserver) {
chatObserver.disconnect();
}
// 채팅 리스트 컨테이너 (예: live_chatting_list_wrapper__)를 찾습니다.
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));

// MutationObserver로 새 메시지 감지
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 });
}

// SPA 대응: URL 변경 시 채팅 옵저버 재설정
function setupSPADetection() {
let lastUrl = location.href;
function onUrlChange() {
if (location.href !== lastUrl) {
lastUrl = location.href;
// 새 DOM 로딩 시간 고려하여 1초 후 옵저버 재설정
setTimeout(setupChatObserver, 1000);
}
}
// pushState, replaceState 후킹
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);
}

// 초기화: 채팅 옵저버 및 SPA 감지 설정
function init() {
setupChatObserver();
setupSPADetection();
}

if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();