// ==UserScript==
// @name Namu Hot Now Beta
// @name:ko 나무위키 실검 알려주는 스크립트 베타
// @namespace https://arca.live/b/namuhotnow
// @version 0.8.9_Beta
// @description 이게 왜 실검?
// @author KEMOMIMI
// @match https://namu.wiki/*
// @match https://arca.live/
// @match https://arca.live/b/*
// @match https://arca.live/e/*
// @match https://arca.live/u/*
// @match https://arca.live/settings/*
// @connect arca.live
// @icon https://www.google.com/s2/favicons?sz=64&domain=namu.wiki
// @grant GM_xmlhttpRequest
// ==/UserScript==
function findLinkByPartialMatch(pairs, searchString) {
for (var i = 0; i < pairs.length; i++) {
if (pairs[i].text.toLowerCase().trim() === searchString.toLowerCase().trim()) {
return [pairs[i].link, pairs[i].badges];
}
}
return [null, null];
}
function getSpansContent() {
var spansContent = [];
var spans = Array.from(document.querySelectorAll('#app ul>li>a>span')).slice(0, 10);
spans.forEach(function(span) {
spansContent.push(span.textContent);
});
return spansContent.join('').trim();
}
var linkElements = [];
var pairs = [];
var previousSpansContent = "";
var storedElements = [];
function removeLinkElements() {
for (var i = 0; i < linkElements.length; i++) {
var linkElement = linkElements[i];
linkElement.parentNode.removeChild(linkElement);
}
linkElements = [];
}
function checkMobileHotkewordOpened(){
const aTags = Array.from(document.querySelector('a[title="아무 문서로 이동"]').parentElement.querySelectorAll('a'));
if (aTags.length > 10) {
return true
}else{
return false
}
}
function checkMobileHotkeword(){
var chk = setInterval(function() {
var svgTags = Array.from(document.querySelector('a[title="아무 문서로 이동"]').parentElement.querySelectorAll('svg'));
if (svgTags.length<5) {
var whyHotElements = document.querySelectorAll('.whyHot');
whyHotElements.forEach(function(element) {
element.remove();
});
const elementsWithParentClass = document.querySelectorAll('.namuHotParentClass');
elementsWithParentClass.forEach(parentElement => {
const childAElement = parentElement.querySelector('a');
if (childAElement) {
parentElement.parentNode.insertBefore(childAElement, parentElement.nextSibling);
parentElement.remove();
}
});
}else if (svgTags.length>=5){
const elementsWithParentClass = document.querySelectorAll('.namuHotParentClass');
let count = 0;
elementsWithParentClass.forEach(parentElement => {
const childAnchorElements = parentElement.querySelectorAll('a');
childAnchorElements.forEach(anchorElement => {
if (anchorElement.getAttribute('href') === '#') {
count++;
}
});
});
if (count == 0) {
const elementsWithParentClass = document.querySelectorAll('.namuHotParentClass');
elementsWithParentClass.forEach(function(element) {
element.remove();
});
}
if (elementsWithParentClass.length == 0) {
if (checkMobileHotkewordOpened()) {
clearInterval(chk);
refreshLink(2);
}
}
}
}, 100);
}
//실검챈에서 게시물 링크를 수집하여 pairs에 저장하는 함수
//page : 긁어올 실검챈 페이지 길이
function updatePairs(page) {
return new Promise((resolve, reject) => {
let completedRequests = 0;
for (var i = 1; i <= page; i++) {
GM_xmlhttpRequest({
method: 'GET',
url: 'https://arca.live/b/namuhotnow?p=' + i,
onload: function(response) {
// 기존의 onload 함수 내용
const htmlData = response.responseText;
const parser = new DOMParser();
const doc = parser.parseFromString(htmlData, 'text/html');
var elements = doc.querySelectorAll('.article-list .list-table a:not(.notice)');
storedElements = Array.from(elements);
elements.forEach(function(element) {
const badgesElement = element.querySelector('.badges');
var badgesText = badgesElement ? badgesElement.textContent.trim() : '이왜실?';
var link = element.getAttribute('href');
var titleElement = element.querySelector('.title');
var text = titleElement ? titleElement.innerText.trim() : '';
pairs.push({text: text, link: link, badges : badgesText});
if(/^.+\)/.test(text)){
var textArray = text.replace(/^.*?\)\s*/, '').split(',').map(function(item) {
return item.trim();
});
textArray.forEach(function(subText) {
pairs.push({ text: subText, link: link, badges : badgesText});
});
}
if (text.includes(')')) {
var tempArray = text.split(')').map(function(item) {
return item.trim();
});
tempArray.forEach(function(subText) {
var subArray = subText.split(',').map(function(item) {
return item.trim();
});
subArray.forEach(function(finalText) {
pairs.push({ text: finalText, link: link, badges : badgesText});
});
});
}
if (text.includes(',')) {
textArray = text.split(',').map(function(item) {
return item.trim();
});
textArray.forEach(function(subText) {
pairs.push({ text: subText, link: link, badges : badgesText});
});
}
if (text.includes(' ')) {
textArray = text.split(' ').map(function(item) {
return item.trim();
});
textArray.forEach(function(subText) {
pairs.push({ text: subText, link: link, badges : badgesText});
});
}
if (text.includes('(')) {
var removeParenthesis = text.replace(/\s*\([^)]*\)$/, '');
pairs.push({ text: removeParenthesis.trim(), link: link, badges : badgesText});
}
});
completedRequests++;
if (completedRequests === page) {
resolve(); // 모든 요청이 완료되면 Promise를 resolve
}
},
onerror: function(error) {
reject(error); // 에러 발생 시 Promise를 reject
}
});
}
//키워드 수동 연결
pairs.push({ text: "나무위키 실검 알려주는 채널", link: "/b/namuhotnow/112775488", badges : "❗️공지"});
});
}
async function refreshLink(type) {
try {
await updatePairs(2);
} catch (error) {
console.error("업데이트 중 오류:", error);
}
if(type == 0){
var realtimeList = Array.from(document.querySelectorAll('#app ul>li>a>span')).slice(0, 10);
realtimeList.forEach(function(titleElement) {
var [resultLink, resultBadges] = findLinkByPartialMatch(pairs, titleElement.innerText.trim());
if (resultLink != null){
var linkElement = document.createElement('a');
linkElement.href = 'https://arca.live' + resultLink;
linkElement.textContent = resultBadges;
linkElement.display = 'flex';
linkElement.width = '40%';
linkElement.target="_blank";
linkElement.setAttribute('data-v-f1cb35f1', '');
linkElement.setAttribute('data-v-8eeb36ac', '');
linkElement.className = 'ECDfhgnB _6-LImOrz';
const parentLiTag = titleElement ? titleElement.parentElement.parentElement : null;
parentLiTag.querySelector('a').style.width = "60%";
parentLiTag.appendChild(linkElement);
linkElements.push(linkElement);
}
});
}else if(type == 1){
var firstLinkList = document.querySelector('aside .link-list');
var arcalinkElements = firstLinkList.querySelectorAll('a');
var titleArray = [];
arcalinkElements.forEach(function(aLinkElement) {
var [resultLink, resultBadges] = findLinkByPartialMatch(pairs, aLinkElement.getAttribute('title'));
if(resultLink != null){
aLinkElement.style.paddingRight = "1em";
var newSpanHTML = `
<div style="padding:.15rem .5rem .15rem 0; user-select: auto;">
<span class="leaf-info float-right" title="[${resultBadges}] ${aLinkElement.getAttribute('title')} 왜 실검?" style="margin:0; user-select: auto;"><time style="user-select: auto;"><a href="${resultLink}" target="_blank" style="font-size: 1em; padding-Right: 0; user-select: auto;">${resultBadges}</a></time></span>
<a href="//namu.wiki/Go?q=${aLinkElement.getAttribute('title')}" target="_blank" title="${aLinkElement.getAttribute('title')}" style="padding:.15rem 1.5rem .15rem 0; user-select: auto;">${aLinkElement.getAttribute('title')}</a>
</div>
`;
aLinkElement.insertAdjacentHTML('beforebegin', newSpanHTML);
aLinkElement.remove()
}
});
}else if(type == 2){
var namuHotParentClass = document.querySelectorAll('.namuHotParentClass');
if (!namuHotParentClass[0]) {
const aTags = Array.from(document.querySelector('a[title="아무 문서로 이동"]').parentElement.querySelectorAll('a'));
const mobileList = aTags.length > 10 ? aTags.slice(-10) : aTags;
mobileList.forEach(function(element) {
var [resultLink, resultBadges] = findLinkByPartialMatch(pairs, element.innerText.trim());
var newParent = document.createElement('span');
newParent.classList.add('namuHotParentClass');
if (resultLink != null){
var linkElement = document.createElement('a');
linkElement.href = 'https://arca.live' + resultLink;
linkElement.textContent = resultBadges;
linkElement.width = '20px';
linkElement.target="_blank";
linkElement.title = resultBadges;
linkElement.classList.add('whyHot');
linkElement.setAttribute('data-v-f1cb35f1', '');
linkElement.setAttribute('data-v-8eeb36ac', '');
linkElement.className = 'ECDfhgnB _6-LImOrz';
element.style.width = "70%";
var beforePseudoElement = window.getComputedStyle(element, ':before');
element.parentNode.insertBefore(newParent, element);
newParent.appendChild(element);
newParent.appendChild(linkElement);
newParent.style.display = 'flex';
linkElements.push(linkElement);
}else{
element.parentNode.insertBefore(newParent, element);
newParent.appendChild(element);
element.style.width = "100%";
newParent.style.display = 'flex';
}
});
checkMobileHotkeword();
}
}
}
function isPC() {
if ((window.innerWidth || document.documentElement.clientWidth) >= 1024) {
return true;
} else {
return false;
}
}
function appendStyle() {
var style = document.createElement('style');
var css = `
${[...Array(10)].map((_, i) => `
.namuHotParentClass:nth-of-type(${i + 1}) > a:nth-child(1):before {
content: "${i + 1}." !important;
}`).join('')}
.whyHot {
align-items: center;
border: 1px solid transparent;
border-radius: var(--nav-bar-child-radius-var);
display: flex;
padding: var(--search-box-suggest-item-gutter-y-var) var(--search-box-suggest-item-gutter-x-var);
text-decoration: none;
word-break: break-all;
}
`;
style.appendChild(document.createTextNode(css));
document.head.appendChild(style);
}
(function() {
'use strict';
if (window.location.href.includes('namu.wiki')) {
if(isPC()){
setInterval(function() {
var content = getSpansContent();
if (content.length > 0 && previousSpansContent !== getSpansContent()) {
previousSpansContent = getSpansContent();
removeLinkElements();
refreshLink(0);
}
}, 100);
}else{
var interNamuMobile = setInterval(function() {
if (checkMobileHotkewordOpened()) {
clearInterval(interNamuMobile);
appendStyle();
refreshLink(2);
}
}, 50);
}
}
if (/arca.live\/b\/namuhotnow\/[0-9]+/.test(window.location.host + window.location.pathname)) {
const spanElement = document.querySelector('span.badge.badge-success.category-badge');
var isNotice = false
if (spanElement) {
const textContent = spanElement.textContent.trim();
if (textContent.includes("공지")) {
isNotice = true;
}
}
if(!isNotice){
const titleElement = document.querySelector('.title-row > .title');
const titleOriginalText = titleElement.lastChild.data.trim();
var pattern = /.+\)\s.+/;
var prefix = "";
var suffix = titleOriginalText;
if (pattern.test(titleOriginalText)) {
pattern = /^(.+)\)\s(.+)$/;
const match = titleOriginalText.match(pattern);
prefix = match[1]+") "; // "괄호부분) "
suffix = match[2]; // "실검 키워드"
}
titleElement.removeChild(titleElement.lastChild);
titleElement.appendChild(document.createTextNode("\n"));
titleElement.appendChild(document.createTextNode(prefix));
suffix.split(', ').forEach((title, idx, array) => {
var linkElement = document.createElement('a');
linkElement.href = 'https://namu.wiki/w/' + title;
linkElement.textContent = title;
linkElement.target="_blank"
const element = document.querySelector('.containe-fluid.board-article');
if (element) {
const bgColor = window.getComputedStyle(element).backgroundColor;
const rgbValues = bgColor.match(/\d+/g);
if (rgbValues && rgbValues.length >= 3) {
const allAbove200 = rgbValues.slice(0, 3).every(value => Number(value) > 200);
if (allAbove200){
linkElement.style.color = '#144c75'; // 진한 남색
}else{
linkElement.style.color = '#a8cfed'; // 연한 하늘색
}
} else {
console.log('RGB 값을 확인할 수 없습니다.');
}
} else {
console.log('해당 클래스를 가진 요소를 찾을 수 없습니다.');
}
linkElement.style.cursor = 'pointer';
titleElement.appendChild(linkElement);
if (idx + 1 < array.length) {
titleElement.appendChild(document.createTextNode(", "));
}
});
}
} else if(/^arca\.live\/b\/namuhotnow\/?$/.test(window.location.host + window.location.pathname)){
fetch('https://search.namu.wiki/api/ranking')
.then(response => response.json())
.then(data => {
const rankings = {};
const emojis = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '️5️⃣', '6️⃣', '️7️⃣', '️8️⃣', '9️⃣', '🔟'];
data.slice(0, 10).forEach((item, index) => {
const emoji = emojis[index];
rankings[item] = emoji;
});
const keywords = Object.keys(rankings);
const titleElements = document.querySelectorAll('.table .title');
titleElements.forEach(element => {
let text = element.textContent;
keywords.forEach(keyword => {
if (text.includes(keyword)) {
text = text.replace(keyword, `<b><u>${rankings[keyword]}${keyword}</u></b>`);
}
});
element.innerHTML = text;
});
})
.catch(error => console.error('Error:', error));
}
else if (window.location.href.includes('arca.live') && !window.location.pathname.startsWith("/b/")) {
var intervalId = setInterval(function() {
var firstLinkLista = document.querySelector('aside .link-list a');
if (firstLinkLista && firstLinkLista.innerHTML !== " ") {
clearInterval(intervalId);
refreshLink(1);
}
}, 50);
}
})();