您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
喵喵喵
// ==UserScript== // @name 咱猫之全部变成小南娘Plus! // @namespace https://penyo.ru/ // @version 1.0.9.1 // @description 喵喵喵 // @author xia // @match *://*/* // @exclude *://greasyfork.org/* // @grant none // @license WTFPL // ==/UserScript== /** * 是否影响输入框 * * 警告!除非你知道改动此项会引发什么结果,否则不应改动! */ const affectInput = true; (function () { "use strict"; const blacklist = [ 'runjs.app', ]; const currentHost = window.location.hostname; if (blacklist.includes(currentHost)) { return; } // ctm requestIdleCallback let deadlineTime; let callback = []; let channel = new MessageChannel(); let port1 = channel.port1; let port2 = channel.port2; port2.onmessage = () => { const timeRemaining = () => deadlineTime - performance.now(); const _timeRemain = timeRemaining(); if (_timeRemain > 0 && callback.length) { const deadline = { timeRemaining, didTimeout: _timeRemain < 0 }; let callbackList = [...callback]; callback = []; callbackList.forEach(cb => cb(deadline)); } requestAnimationFrame(rafTime => { deadlineTime = rafTime + 16.667; port1.postMessage(null); }); }; function ctmRequestIdleCallback(cb) { requestAnimationFrame(rafTime => { deadlineTime = rafTime + 16.667; port1.postMessage(null); }); callback.push(cb); } let replacementHistory = {}; const elementToMatch = [ "title", "h1", "h2", "h3", "h4", "h5", "h6", "p", "article", "section", "blockquote", "li", "a", "CC", "span.ProfileHeader-name", "span.AuthorInfo-name", "span.bili-rich-text-module.at", "span.bili-dyn-title__text", "span.u_username_title", "span.userinfo_username", "span.lzl_content_main", "div.bili-danmaku-x-dm", "div.CommentContent" ]; /** * @param {Element} root */ function replace(root) { const replacer = (str) => { let rep = str .replace(/我们/g, "咱喵和其它猫猫们") .replace(/他|同事/g, "其它猫猫") .replace(/大家/g, "各位猫猫们") .replace(/手指/g, "猫爪") .replace(/手/g, "爪") .replace(/他妈的/g, "他爹的") .replace(/哈哈/g, "嗯哼") .replace(/(爸爸|妈妈)([\u4e00-\u9fff_a-zA-Z])/g, (match, $1, $2) => { if ($2 === '猫') return $1 + $2; return $1 + '猫' + $2; }) .replace(/^个人|\s个人|本人|我个人|(?<!自|本)我|(?<=[\u3002\uff1b\uff0c\u3001\uff1a\uff1f!?,.])个人|个人(?=[认感觉])/g, (match) => { return Math.random() < 0.85 ? "咱喵" : "老娘"; }) .replace(/个/g, "只") .replace(/你们/g, "汝等") .replace(/你|您/g, "汝") .replace(/用户|(?<![每个只])人(?![类员民才口])/g, (match) => { return Math.random() < 0.7 ? "猫猫" : "顺÷"; }) .replace(/孝子|xz|卫兵|小丑|资本|水军|困难|苦难|挫折|海军|二游|节奏/g, "杂鱼") .replace(/工作|编程|实习|面试|考研|拧螺丝|计算机|技术|恋爱|溜冰|爆改|白嫖|洗白|抄袭|借鉴|退坑|干活|好似/g, "援交") .replace( /([也矣兮乎者焉哉]|[啊吗呢吧哇呀哦嘛喔咯呜捏])([ !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~\u3000-\u303F\uFF00-\uFFEF]|$)/g, (_, $1, $2) => `喵${orophilia()}${$2}` ) .replace( /([的了辣])([!"#$%&'()*+,-./:;/,=>?@[\]^_`{|}~\u3000-\u303F\uFF00-\uFFEF]|\s+(?!<|\w)|$)/g, (_, $1, $2) => `${$1}喵${orophilia()}${$2}` ) .replace(/([\u4e00-\u9fff_a-zA-Z])([\u4e00-\u9fff_a-zA-Z])([\uff0c,])/g, (match, $1, $2, $3) => { const key = $1 + $2 + $3; if (!replacementHistory[key]) { replacementHistory[key] = Math.random(); const r = replacementHistory[key]; let res = $1 + $2; if ($2 !== "喵" && $2 !== "す" && $2 !== "说" && $2 !== "哦" && $2 !== "w" && $2 !== "💗" && $2 !== "啊") { res += r < 0.2 ? '喵' : r < 0.3 ? '的说' : r < 0.45 ? '哦' : ''; } else { return key; } res += r < 0.09 ? '💗' : r < 0.18 ? '💗💗' : r < 0.27 ? 'w' : r < 0.36 ? 'ww' : ''; return res + $3; } else { return key; } }) .replace(/([\u4e00-\u9fff_a-zA-Z])([\u4e00-\u9fff_a-zA-Z])([\u3002\uff1b\uff1f.?])$/g, (match, $1, $2, $3) => { const key = $1 + $2 + $3; if (!replacementHistory[key]) { replacementHistory[key] = Math.random(); } const r = replacementHistory[key]; let res = $1 + $2; if ($2 !== "喵" && $2 !== "す") { res += r < 0.75 ? '喵' : ''; } res += r < 0.18 ? '💗' : r < 0.27 ? '💗💗' : r < 0.38 ? '~' : r < 0.48 ? 'w' : r < 0.55 ? 'ww' : r < 0.62 ? '~~' : $3; return res; }) .replace(/([\u4e00-\u9fff_a-zA-Z])([\u4e00-\u9fff_a-zA-Z])([\u3002\uff1b\uff1f.?])([“”""])$/g, (match, $1, $2, $3, $4) => { const key = match; if (!replacementHistory[key]) { replacementHistory[key] = Math.random(); } const r = replacementHistory[key]; let res = $1 + $2; if ($2 !== "喵" && $2 !== "す") { res += r < 0.75 ? '喵' : ''; } res += r < 0.18 ? '💗' : r < 0.27 ? '💗💗' : r < 0.38 ? '~' : r < 0.48 ? 'w' : r < 0.55 ? 'ww' : r < 0.62 ? '~~' : $3; res += $4; return res; }); if (str.length > 12) { rep = rep .replace(/([\u4e00-\u9fa5])$/, (match) => { if (match !== '喵' && match !== "す") { const r = Math.random(); let res = match; res += Math.random() < 0.8 ? '喵' : ''; res += r < 0.18 ? '💗' : r < 0.27 ? '💗💗' : r < 0.38 ? '~' : r < 0.48 ? 'w' : r < 0.55 ? 'ww' : r < 0.62 ? '~~' : ''; return res; } else { return match; } }) .replace(/^[\u4e00-\u9fff_a-zA-Z]{2}/, (match) => { if (match !== '咱喵' && !replacementHistory[match]) { replacementHistory[match] = Math.random(); const r = replacementHistory[match]; return (r < 0.05 ? '咱喵就是说啊,' : r < 0.1 ? '咱喵就是说,' : r < 0.15 ? '咱喵觉得' : '') + match; } else { return match; } }) } return rep; }; const orophilia = () => (Math.random() < 0.2 ? "です" : ""); function insertEmojiImg(element, where, emoji, specialStyle = {}) { let emojiImg = document.createElement('img'); emojiImg.src = `https://emojicdn.elk.sh/${emoji}?style=apple`; emojiImg.style.height = '1.2em'; emojiImg.style.verticalAlign = 'sub'; if (where === 'afterbegin') { emojiImg.style.marginRight = '1.5px'; } if (where === 'beforeend') { emojiImg.style.marginLeft = '1.5px'; } for (let style in specialStyle) { emojiImg.style[style] = specialStyle[style]; } element.insertAdjacentElement(where, emojiImg); } let cb = () => { // 如果有选中的文本,则不进行替换 if (window.getSelection().toString()) return; root .querySelectorAll( elementToMatch .concat(elementToMatch.map((name) => name + " *")) .concat(affectInput ? ["input"] : []) .join(",") ) .forEach((candidate) => { if (candidate.nodeName == "INPUT") { candidate.value = replacer(candidate.value); } else if ( candidate.textContent && candidate.textContent == candidate.innerHTML.trim() ) { candidate.textContent = replacer(candidate.textContent); } else if ( Array.from(candidate.childNodes).filter((c) => c.nodeName == "BR") ) { Array.from(candidate.childNodes).forEach((maybeText) => { if (maybeText.nodeType == Node.TEXT_NODE) { maybeText.textContent = replacer(maybeText.textContent); } }); } }); // 昵称添加emoji // 知乎 root.querySelectorAll('span.ProfileHeader-name:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('a.css-10u695f:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('span.AuthorInfo-name > div > a.UserLink-link[data-za-detail-view-element_name="User"]:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.setAttribute('name-modified', 'true'); }); // bilibili root.querySelectorAll('div.opus-module-author__name:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('div#user-name > a:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('div.nickname:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('p#contents > a[data-user-profile-id]:not([name-modified])') .forEach((element) => { let textNode = element.firstChild; insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.insertAdjacentText('afterbegin', '@'); textNode.nodeValue = textNode.nodeValue.replace('@', ''); element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('a.bili-user-profile-view__info__uname:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬', { marginRight: '-1.5px' }); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞', { marginLeft: '-3px' }); element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('span.bili-rich-text-module.at:not([name-modified])') .forEach((element) => { let textNode = element.firstChild; insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞', { marginLeft: '0px' }); element.insertAdjacentText('afterbegin', '@'); textNode.nodeValue = textNode.nodeValue.replace('@', ''); if (textNode.nodeValue.endsWith(':')) { element.insertAdjacentText('beforeend', ':'); textNode.nodeValue = textNode.nodeValue.replace(':', ''); } element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('a.nickname-item:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('span.bili-dyn-title__text:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬', { marginRight: '-3px' }); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞', { marginLeft: '-4.5px' }); element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('a.up-name:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬', { marginRight: '-3px' }); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.setAttribute('name-modified', 'true'); }); // 贴吧 root.querySelectorAll('a.p_author_name:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('span.u_username_title:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('span.userinfo_username:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('div.lzl_cnt > a.j_user_card:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.setAttribute('name-modified', 'true'); }); root.querySelectorAll('span.lzl_content_main > a.j_user_card:not([name-modified])') .forEach((element) => { insertEmojiImg(element, 'afterbegin', '🍬'); insertEmojiImg(element, 'afterbegin', '🏳️⚧️'); insertEmojiImg(element, 'beforeend', '🥞'); element.setAttribute('name-modified', 'true'); }); }; if (!window.requestIdleCallback) { ctmRequestIdleCallback(cb); } else { window.requestIdleCallback(cb); } } /** * @param {Element} root */ async function afterDomLoaded(root) { if (!root) return; const fn = () => { replace(root); root.querySelectorAll("*").forEach(async (node) => { if (node.shadowRoot) { await afterDomLoaded(node.shadowRoot); } }); }; while (document.readyState == "loading") { await new Promise((r) => setTimeout(r, 1000)); } fn(); } afterDomLoaded(document); setInterval(() => afterDomLoaded(document), 2500); })();