// ==UserScript== // @name 숲 멀티뷰 시청자 제거기 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 숲 생방송 시청자 목록을 가져오고 멀티뷰를 제거합니다. // @author asdi // @match https://play.sooplive.co.kr/* // @grant none // @downloadURL none // ==/UserScript== (function () { 'use strict'; // 팝업창 생성 const popup = document.createElement('div'); popup.style.position = 'fixed'; popup.style.top = '50%'; // 세로 중앙에 위치하도록 popup.style.left = '0'; // 가로 왼쪽에 위치하도록 popup.style.transform = 'translateY(-50%)'; // 세로 중앙 정렬 popup.style.zIndex = '1000'; popup.style.width = '350px'; popup.style.padding = '15px'; popup.style.backgroundColor = '#f8f9fa'; popup.style.border = '1px solid #ccc'; popup.style.borderRadius = '8px'; popup.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.1)'; popup.style.fontSize = '14px'; popup.style.fontFamily = 'Arial, sans-serif'; popup.style.color = '#333'; popup.innerHTML = `
닉네임이 여기에 표시됩니다.
결과가 여기에 표시됩니다.

결과가 여기에 표시됩니다.
`; document.body.appendChild(popup); // 닫기 버튼 핸들러 document.getElementById('closePopup').addEventListener('click', () => { document.body.removeChild(popup); // 팝업창 삭제 }); // userIdList에서 괄호 부분을 무시하고 중복 없는 아이디 리스트를 구하는 함수 const getUniqueUserIdList = (userIdList) => { const uniqueUserIds = new Set(); userIdList.forEach(userId => { const baseUserId = userId.replace(/\(\d+\)$/, ''); uniqueUserIds.add(baseUserId); }); return [...uniqueUserIds]; }; // 닉네임 가져오기 버튼 핸들러 document.getElementById('getNickName').addEventListener('click', async () => { const nicknameElement = document.querySelector('a#infoNickName'); const nicknameDisplay = document.getElementById('nicknameDisplay'); const nicknameResults = document.getElementById('nicknameResults'); if (nicknameElement) { const nickname = nicknameElement.textContent.trim(); nicknameDisplay.textContent = `닉네임: ${nickname}`; try { liveView.Chat.chatUserListLayer.reconnect(); liveView.playerController.sendChUser(); const viewerText = document.getElementById('nAllViewer').textContent; const viewerNumber = parseInt(viewerText.replace(/,/g, '')); console.log('Viewer Number:', viewerNumber); // 3초 대기 await new Promise(resolve => setTimeout(resolve, 3000)); const userList = liveView.Chat.chatUserListLayer; const userIdList = [ ...Object.keys(userList.userListSeparatedByGrade.fan), ...Object.keys(userList.userListSeparatedByGrade.manager), ...Object.keys(userList.userListSeparatedByGrade.normal), ...Object.keys(userList.userListSeparatedByGrade.subscription), ...Object.keys(userList.userListSeparatedByGrade.vip) ]; const uniqueUserIdList = getUniqueUserIdList(userIdList); console.log('Unique User ID List:', uniqueUserIdList); const loginRatio = (uniqueUserIdList.length / viewerNumber * 100).toFixed(2); const resultMessage = `${nickname} - 현재 시청자 수 : ${viewerNumber}, 중복 제거한 로그인 시청자 : ${uniqueUserIdList.length} (로그인 비율 : ${loginRatio}%)`; const nicknameResultsContent = document.getElementById('nicknameResults'); const previousResults = nicknameResultsContent.textContent.trim(); const updatedResults = previousResults ? previousResults + `\n\n${resultMessage}` : resultMessage; nicknameResultsContent.textContent = updatedResults; // localStorage에 저장 const savedResults = localStorage.getItem('allResults') || ''; localStorage.setItem('allResults', savedResults + `\n${resultMessage}`); localStorage.setItem(`uniqueUserIdList_${nickname}`, JSON.stringify(uniqueUserIdList)); } catch (error) { console.error('Error:', error); nicknameResults.textContent = `Error: ${error.message}`; } } else { nicknameDisplay.textContent = '닉네임을 찾을 수 없습니다.'; } }); // 총 시청자 수 구하기 버튼 핸들러 document.getElementById('totalViewerCount').addEventListener('click', () => { const totalViewerResults = document.getElementById('totalViewerResults'); const nicknameKeys = Object.keys(localStorage).filter(key => key.startsWith('uniqueUserIdList_')); if (nicknameKeys.length > 0) { const uniqueViewerLists = []; const nicknames = []; let totalViewerNumber = 0; nicknameKeys.forEach(key => { const nickname = key.replace('uniqueUserIdList_', ''); const uniqueUserIdList = JSON.parse(localStorage.getItem(key)); uniqueViewerLists.push(new Set(uniqueUserIdList)); nicknames.push(nickname); totalViewerNumber += uniqueUserIdList.length; }); const unionSet = new Set(); uniqueViewerLists.forEach(set => set.forEach(viewer => unionSet.add(viewer))); const multiViewExcludedCount = unionSet.size; const nicknameList = nicknames.join(', '); const idCounts = {}; uniqueViewerLists.forEach(set => { set.forEach(viewer => { idCounts[viewer] = (idCounts[viewer] || 0) + 1; }); }); const multiSetUsers = Object.keys(idCounts).filter(viewer => idCounts[viewer] > 1); const multiSetCount = multiSetUsers.length; const now = new Date(); const formattedDate = `${now.getFullYear()}년 ${now.getMonth() + 1}월 ${now.getDate()}일 ${['일', '월', '화', '수', '목', '금', '토'][now.getDay()]} ${now.getHours()}:${now.getMinutes().toString().padStart(2, '0')}`; totalViewerResults.textContent = `집계 시각 : ${formattedDate} ${nicknameList} 의 멀티뷰 제외 로그인 시청자 수 : ${multiViewExcludedCount}명 ( 멀티뷰 포함 : ${totalViewerNumber}, 멀티뷰 중인 시청자 수 : ${multiSetCount} )`; } else { totalViewerResults.textContent = '저장된 결과가 없습니다.'; } }); // 리셋 버튼 핸들러 document.getElementById('resetButton').addEventListener('click', () => { localStorage.removeItem('allResults'); Object.keys(localStorage).forEach(key => { if (key.startsWith('uniqueUserIdList_')) { localStorage.removeItem(key); } }); document.getElementById('nicknameResults').textContent = '결과가 여기에 표시됩니다.'; document.getElementById('totalViewerResults').textContent = '결과가 여기에 표시됩니다.'; alert('모든 결과가 리셋되었습니다.'); }); // localStorage에서 저장된 모든 결과 가져오기 const savedResults = localStorage.getItem('allResults'); if (savedResults) { document.getElementById('nicknameResults').textContent = savedResults; } })();