// ==UserScript== // @namespace https://tampermonkey.myso.kr/ // @name 네이버 블로그 이웃,그룹 관리 어드밴스드 // @description 네이버 블로그의 이웃,그룹 관리 기능을 확장합니다. // @copyright 2021, myso (https://tampermonkey.myso.kr) // @license Apache-2.0 // @version 1.0.15 // @author Won Choi // @connect naver.com // @match *://admin.blog.naver.com/BuddyListManage* // @grant GM_addStyle // @grant GM_xmlhttpRequest // @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@1.0.48/assets/vendor/gm-app.js // @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@1.0.48/assets/vendor/gm-add-style.js // @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@1.0.48/assets/vendor/gm-add-script.js // @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@1.0.48/assets/vendor/gm-xmlhttp-request-async.js // @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@1.0.48/assets/donation.js // @downloadURL https://update.greasyfork.icu/scripts/428664/%EB%84%A4%EC%9D%B4%EB%B2%84%20%EB%B8%94%EB%A1%9C%EA%B7%B8%20%EC%9D%B4%EC%9B%83%2C%EA%B7%B8%EB%A3%B9%20%EA%B4%80%EB%A6%AC%20%EC%96%B4%EB%93%9C%EB%B0%B4%EC%8A%A4%EB%93%9C.user.js // @updateURL https://update.greasyfork.icu/scripts/428664/%EB%84%A4%EC%9D%B4%EB%B2%84%20%EB%B8%94%EB%A1%9C%EA%B7%B8%20%EC%9D%B4%EC%9B%83%2C%EA%B7%B8%EB%A3%B9%20%EA%B4%80%EB%A6%AC%20%EC%96%B4%EB%93%9C%EB%B0%B4%EC%8A%A4%EB%93%9C.meta.js // ==/UserScript== // ==OpenUserJS== // @author myso // ==/OpenUserJS== GM_App(async function main() { GM_donation('.admin_set_buddy'); GM_addScript('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js'); GM_addScript('https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment-with-locales.min.js'); GM_addScript(() => { async function delete_buddy(selfishes) { const blogId = new URL(location.href).searchParams.get('blogId') || location.pathname.split('/')[1]; const uri = new URL('https://admin.blog.naver.com/BuddyDelete.naver'); const formData = new FormData(); selfishes.map(o=>formData.append('buddyBlogNo', o.blogNo)); formData.append('blogId', blogId); formData.append('on', ''); formData.append('force', 'true'); await fetch(uri.toString(), { method: 'POST', body: formData }); } window.delete_buddy = delete_buddy; }) GM_addScript(() => { async function search_buddy_page(callback, page = 1, results = []) { const blogId = new URL(location.href).searchParams.get('blogId') || location.pathname.split('/')[1]; const res = await fetch(`https://admin.blog.naver.com/BuddyListManage.naver?blogId=${blogId}¤tPage=${page}&searchText=&orderType=adddate`).then(r=>r.text()); const doc = document.createElement('div'); doc.innerHTML = res; const pagination = Array.from(doc.querySelector('div.paginate_re').children), pagenation_last = pagination[pagination.length - 1]; const has_next = pagenation_last.tagName == 'A' && !!pagenation_last.className, has_next_valid = pagenation_last.tagName != 'STRONG'; const usernames_rows = Array.from(doc.querySelectorAll('tr a[href*="blog.naver.com"], tr a[href*=".blog.me"]')); const usernames = usernames_rows.map(e=>{ const uri = new URL(e.href); const tr = e.closest('tr'); const group = (() => { const el = tr.querySelector('td.groupwrap, td:nth-child(2)'); return _.trim(el ? el.innerText : ''); })(); const type = (() => { const el = tr.querySelector('td.type, td:nth-child(3)'); return _.trim(el ? el.innerText : ''); })(); const blogNo = (() => tr.querySelector('td:first-child input').value)(); const blogId = (() => { if(uri.hostname.includes('.blog.me')) return uri.hostname.replace('.blog.me', ''); if(uri.hostname.includes('blog.naver.com')) return uri.pathname.replace('/', ''); return uri.hostname; })(); const blogUrl = (() => e.href)(); const blogName = (() => { const el = tr.querySelector('td.buddy a, td:nth-child(4) a'); return _.trim(el ? el.innerText : blogId); })(); const nickName = (() => { const el = tr.querySelector('td.buddy span.nickname, td:nth-child(4) span.nickname'); return _.trim(el ? el.innerText : blogId); })(); const lastPostAt = (() => { const el = tr.querySelector('td:nth-child(6)'); const date = _.trim(el ? el.innerText : ''); return /^[\d\.]+$/.test(date) && moment(date, 'YY.MM.DD.').toISOString(true); })(); const createdAt = (() => { const el = tr.querySelector('td:nth-child(7)'); const date = _.trim(el ? el.innerText : ''); return /^[\d\.]+$/.test(date) && moment(date, 'YY.MM.DD.').toISOString(true); })(); return { blogNo, blogId, blogUrl, blogName, nickName, group, type, lastPostAt, createdAt }; }); if(callback) callback(usernames); results.push(...usernames); return (has_next || has_next_valid) ? search_buddy_page(callback, page+1, results) : results.filter((o,i)=>results.indexOf(o)==i); } window.search_buddy = search_buddy_page; }) GM_addScript(() => { async function search_buddy_me_page(callback, page = 1, results = []) { const blogId = new URL(location.href).searchParams.get('blogId') || location.pathname.split('/')[1]; const res = await fetch(`https://admin.blog.naver.com/BuddyMeManage.naver?relation=all&blogId=${blogId}¤tPage=${page}`).then(r=>r.text()); const doc = document.createElement('div'); doc.innerHTML = res; const pagination = Array.from(doc.querySelector('div.paginate_re').children), pagenation_last = pagination[pagination.length - 1]; const has_next = pagenation_last.tagName == 'A' && !!pagenation_last.className, has_next_valid = pagenation_last.tagName != 'STRONG'; const usernames_rows = Array.from(doc.querySelectorAll('tr a[href*="blog.naver.com"], tr a[href*=".blog.me"]')); const usernames = usernames_rows.map(e=>{ const uri = new URL(e.href); const tr = e.closest('tr'); const type = (() => { const el = tr.querySelector('td.groupwrap, td:nth-child(3)'); const followed_type1 = el.querySelector('a > img[alt="서로이웃신청"]') ? '' : '서로이웃' const followed_type2 = el.querySelector('a > img[alt="이웃추가"]') ? '' : '이웃' return followed_type1 || followed_type2 || '비이웃'; })(); const blogNo = (() => tr.querySelector('td:first-child input').value)(); const blogId = (() => { if(uri.hostname.includes('.blog.me')) return uri.hostname.replace('.blog.me', ''); if(uri.hostname.includes('blog.naver.com')) return uri.pathname.replace('/', ''); return uri.hostname; })(); const blogUrl = (() => e.href)(); const blogName = (() => { const el = tr.querySelector('td.buddy a, td:nth-child(2) a'); return _.trim(el ? el.innerText : blogId); })(); const nickName = (() => { const el = tr.querySelector('td.buddy span.nickname, td:nth-child(2) span.nickname'); return _.trim(el ? el.innerText : blogId); })(); const createdAt = (() => { const el = tr.querySelector('td.date, td:nth-child(4)'); const date = _.trim(el ? el.innerText : ''); return /^[\d\.]+$/.test(date) && moment(date, 'YY.MM.DD.').toISOString(true); })(); return { blogNo, blogId, blogUrl, blogName, nickName, type, createdAt }; }); if(callback) callback(usernames); results.push(...usernames); return (has_next || has_next_valid) ? search_buddy_me_page(callback, page+1, results) : results.filter((o,i)=>results.indexOf(o)==i); } window.search_buddy_me = search_buddy_me_page; }) GM_addScript(() => { const html = ` 네이버 블로그 이웃,그룹 관리 어드밴스드
나를 이웃한 사람 : {{ followers.length }}명 / 내가 이웃한 사람 : {{ following.length }}명
이웃추가일
필터링단어
그룹명 이웃상태 닉네임 (아이디), 블로그명 최근작성 이웃추가 관리메뉴
{{ user.group }} {{ user.type }}
{{ user.nickName }} ({{user.blogId}})
{{ user.lastPostAt.substr(0, 10) }} {{ user.createdAt.substr(0, 10) }}
`; const $window = window.open('about:blank', '_buddy_window', 'width=960,height=720'); setTimeout(async ()=>{ $window.document.write(html); setTimeout(async () => { await search_buddy((data) => { if($window.closed) throw new Error('closed'); $window.document.dispatchEvent(new CustomEvent('append.following', { detail: { data } })); }).catch(e=>null); await search_buddy_me((data) => { if($window.closed) throw new Error('closed'); $window.document.dispatchEvent(new CustomEvent('append.followers', { detail: { data } })) }).catch(e=>null); $window.document.dispatchEvent(new CustomEvent('append.finish')) }, 300); }, 300); }) });