// ==UserScript== // @namespace https://tampermonkey.myso.kr/ // @name 네이버 블로그 이웃,그룹 관리 어드밴스드 // @description 네이버 블로그의 이웃,그룹 관리 기능을 확장합니다. // @copyright 2021, myso (https://tampermonkey.myso.kr) // @license Apache-2.0 // @version 1.0.8 // @author Won Choi // @match *://admin.blog.naver.com/BuddyListManage* // @grant GM_addStyle // @grant GM_xmlhttpRequest // @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@latest/assets/vendor/gm-app.min.js // @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@latest/assets/vendor/gm-add-style.min.js // @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@latest/assets/vendor/gm-add-script.min.js // @require https://cdn.jsdelivr.net/npm/kr.myso.tampermonkey@latest/assets/donation.min.js // @downloadURL none // ==/UserScript== // ==OpenUserJS== // @author myso // ==/OpenUserJS== async function inject_js(opt) { return new Promise((resolve, reject) => { var el = document.createElement('script'); el.type = 'text/javascript'; function resolved() { el.parentNode.removeChild(el); resolve(); } if(typeof opt === 'string') { el.onload = resolved; el.src = opt; } if(typeof opt === 'object') { el.onload = resolved; el.src = opt.src; el.integrity = opt.integrity; el.setAttribute('crossorigin', 'anonymous'); } if(typeof opt === 'function') el.textContent = `(${opt})();`; if(el.src || el.textContent) { el.onerror = reject; document.head.prepend(el); }else reject(); if(typeof opt === 'function') resolved(); }); } GM_App(async function main() { GM_donation('.admin_set_buddy'); await inject_js({ integrity: 'sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==', src: 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js' }); await inject_js({ integrity: 'sha512-LGXaggshOkD/at6PFNcp2V2unf9LzFq6LE+sChH7ceMTDP0g2kn6Vxwgg7wkPP7AAtX+lmPqPdxB47A0Nz0cMQ==', src: 'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment-with-locales.min.js' }); await inject_js(() => { 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.nhn'); 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; }) await inject_js(() => { 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.nhn?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; }) await inject_js(() => { 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.nhn?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; }) await inject_js(() => { const html = `
그룹명 | 이웃상태 | 닉네임 (아이디), 블로그명 | 최근작성 | 이웃추가 | 관리메뉴 |
---|---|---|---|---|---|
{{ user.group }} | {{ user.type }} |
{{ user.nickName }} ({{user.blogId}})
|
{{ user.lastPostAt.substr(0, 10) }} | {{ user.createdAt.substr(0, 10) }} |