// ==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);
})();