您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Shadow blocks user (only blocks on responses and timeline of yourself)
当前为
// ==UserScript== // @name Plurk shadow block // @name:zh-TW 噗浪隱形黑名單 // @description Shadow blocks user (only blocks on responses and timeline of yourself) // @description:zh-TW 隱形封鎖使用者(只是會在回應和在河道上看不到被封鎖者的發文、轉噗,其他正常) // @match https://www.plurk.com/* // @version 0.3.3 // @license MIT // @require https://code.jquery.com/jquery-3.5.1.min.js // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant window.onurlchange // @namespace https://gf.qytechs.cn/users/735252 // ==/UserScript== /* jshint esversion: 6 */ /* global $ */ (function () { 'use strict'; const LANG = { DEFAULT: { resp_btn_hide: 'Hide blocked responses', resp_btn_show: 'Show blocked responses', set_alert: 'Incorrect format of nick name!', set_append: 'Append', set_empty: 'There is no one in your blocklist.', set_note: 'A blocked user will not be shown on responses and your timeline,' + ' but is still able to see your profile, follow you,' + ' respond to your plurks or befriend you.', set_remove: 'Remove', set_tab: 'Shadow Block' }, 'zh-hant': { resp_btn_hide: '隱藏被封鎖的回應', resp_btn_show: '顯示被封鎖的回應', set_alert: '帳號格式不正確', set_append: '新增', set_empty: '沒有任何人在黑名單中', set_note: '在回應區和自己的河道上看不到被封鎖者的發文、轉噗;' + '但對方仍可瀏覽您的個人檔案,關注、回應您的訊息,或加您為朋友。', set_remove: '移除', set_tab: '隱形黑名單' } }; let lang = LANG.DEFAULT; const curLang = document.body.parentElement.getAttribute('lang') || ''; if (curLang.toLowerCase() in LANG) lang = LANG[curLang.toLowerCase()]; /* ======= storage ======= */ const DEFAULT_VALUE = { replurk: true, response: true, blocklist: [] }; Object.keys(DEFAULT_VALUE).forEach(k => { if (typeof GM_getValue(k) !== typeof DEFAULT_VALUE[k]) { GM_setValue(k, DEFAULT_VALUE[k]); } }); function valueGetSet (key, val = null) { if (val != null) GM_setValue(key, val); return GM_getValue(key); } /* ============== */ GM_addStyle( '.hide {display:none}' + '.resp-hidden-show {background:#f5f5f9;color:#afb8cc;' + ' font-weight:normal;vertical-align:top;transform:scale(0.9);opacity:0;}' + '.resp-hidden-show.show {opacity:1}' + '.response-status:hover .resp-hidden-show {opacity:1}' + '.resp-hidden-show:hover {background:#afb8cc;color:#fff}' ); if (window.location.pathname.match(/^\/p\/[A-Za-z]\w+$/)) { // responses const respMo = new MutationObserver(responseMutationHandler); respMo.observe($('#plurk_responses .list')[0], { childList: true }); makeButton($('#plurk_responses>.response_box')); // pop window const cboxMo = new MutationObserver(responseMutationHandler); cboxMo.observe($('#cbox_response .list')[0], { childList: true }); makeButton($('#cbox_response>.response_box')); } else if (window.location.pathname === '/Friends/') { $('<li><a void="">' + lang.set_tab + '</a></li>').on('click', function () { window.history.pushState('', document.title, '/Friends/'); $('#pop-window-tabs>ul>li').removeClass('current'); this.classList.add('current'); const $content = $('#pop-window-inner-content .content_inner').empty(); $content.append( '<div class="note">' + lang.set_note + '</div>', '<div class="dashboard">' + ' <div class="search_box"><input>' + ' <button>' + lang.set_append + '</button></div>' + ' <div class="empty">' + lang.set_empty + '</div>' + '</div>'); const $holder = $('<div class="item_holder"></div>').appendTo($content); const usersInfo = Array.from(valueGetSet('blocklist'), id => getUserInfoAsync(id)); if (usersInfo.length) $content.find('.dashboard .empty').addClass('hide'); Promise.all(usersInfo).then(infomations => infomations.forEach(info => { makeBlockedUserItem(info, $holder); })); $content.find('.search_box>button').on('click', function () { const m = this.parentElement.children[0].value.match(/^[A-Za-z]\w+$/); if (m) { const blocklist = valueGetSet('blocklist'); blocklist.push(m[0]); valueGetSet('blocklist', blocklist); this.parentElement.children[0].value = ''; $content.find('.dashboard .empty').addClass('hide'); getUserInfoAsync(m[0]) .then(info => makeBlockedUserItem(info, $holder)); } else { window.alert(lang.set_alert); } }); }).appendTo('#pop-window-tabs>ul'); } else if ($('#nav-account>span').text() === window.location.pathname.substr(1)) { // timeline const cntMo = new MutationObserver(responseMutationTimeline); cntMo.observe($('div.block_cnt')[0], { childList: true }); const formMo = new MutationObserver(responseMutationHandler); formMo.observe($('#form_holder .list')[0], { childList: true }); makeButton($('#form_holder>.response_box')); // pop window const cboxMo = new MutationObserver(responseMutationHandler); cboxMo.observe($('#cbox_response .list')[0], { childList: true }); makeButton($('#cbox_response>.response_box')); } function responseMutationTimeline (records) { records.forEach(mu => { mu.addedNodes.forEach(node => { const up = $(node).find('.td_img>.p_img a')[0].href.split('/').pop(); const u0 = $(node).find('.td_qual a.name')[0].href.split('/').pop(); if (isOnBlockList(up) || isOnBlockList(u0)) { node.classList.add('shadow-block', 'hide'); } }); }); } function responseMutationHandler (records) { records.forEach(mu => { const $btn = $(mu.target).parent().find('.resp-hidden-show'); if (!mu.target.querySelector('.handle-remove')) { $('<div class="handle-remove hide"></div>').prependTo(mu.target); } mu.removedNodes.forEach(node => { if (node.classList.contains('handle-remove')) { $btn.removeClass('show').addClass('hide').text(lang.resp_btn_show); } }); let nBlock = 0; mu.addedNodes.forEach(node => { if (!node.classList.contains('plurk')) return; const u0 = $(node).find('a.name')[0].href.split('/').pop(); if (isOnBlockList(u0)) { nBlock += 1; node.classList.add('shadow-block'); if (!$btn.hasClass('show')) node.classList.add('hide'); } }); if ($btn.hasClass('hide') && nBlock) $btn.removeClass('hide'); }); } function makeButton ($responseBox) { const $formBtn = $('<div>' + lang.resp_btn_show + '</div>'); $formBtn.on('click', function () { $formBtn.toggleClass('show'); this.innerText = $formBtn.hasClass('show') ? lang.resp_btn_hide : lang.resp_btn_show; $responseBox.children('.list').children('.shadow-block') .toggleClass('hide'); }).addClass(['resp-hidden-show', 'button', 'small-button', 'hide']) .insertAfter($responseBox.find('.response-only-owner')); } function makeBlockedUserItem (info, holder) { const $u = $('<div class="user_item user_blocked_users_item"></div>'); $u.append( '<a class="user_avatar" target="_blank">' + '<img class="profile_pic" src="' + info.img + '"></img></a>', '<div class="user_info">' + '<a class="user_link" target="_blank" style="color:#000">' + info.name + '</a>' + '<span class="nick_name">@' + info.id + '</span>' + '<div class="more_info"><br></div>' + '</div>', '<div class="user_action"><a void="" data-id="' + info.id + '" ' + 'class="friend_man icon_only pif-user-blocked has_block" ' + 'title="' + lang.set_remove + '"></a></div>' ); $u.find('a:not(.has_block)').attr('href', '/' + info.id); $u.find('a.has_block').on('click', function () { const blocklist = valueGetSet('blocklist'); for (let i = 0; i < blocklist.length; ++i) { if (blocklist[i] === this.dataset.id) { blocklist.splice(i, 1); valueGetSet('blocklist', blocklist); $u.remove(); break; } } }); $u.appendTo(holder); } function getUserInfoAsync (id) { const ico = 'https://www.plurk.com/favicon.ico'; return new Promise((resolve, reject) => { try { const xhr = new XMLHttpRequest(); xhr.responseType = 'document'; xhr.onload = function () { const b = xhr.responseXML.body; const img = b.querySelector('#profile_pic'); const name = b.querySelector('#full_name>.display_name'); const title = xhr.responseXML.title; resolve({ id: id, img: img ? img.src : ico, name: name ? name.innerText : (title.match(/(.+) \[.+\]/) || title.match(/(.+) - Plurk/))[1] }); }; xhr.onerror = function () { resolve({ id: id, name: id, img: ico }); }; xhr.open('GET', 'https://www.plurk.com/' + id); xhr.send(); } catch (e) { resolve({ id: id, name: id, img: ico }); } }); } function isOnBlockList (user) { return valueGetSet('blocklist').includes(user); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址