Last active
June 30, 2021 16:23
-
-
Save swordfeng/749f68a675a10baa597f52b7d65adc57 to your computer and use it in GitHub Desktop.
比比比比吧歪比歪比比卜比歪比歪比比吧吧歪歪卜比比吧比吧歪歪吧吧吧卜比比歪比吧歪比比比歪卜比比歪比吧比吧比歪比卜比歪歪吧比比吧吧吧歪卜比歪歪吧歪吧比比歪比卜比歪比吧吧吧吧歪吧比卜比歪歪比比吧比比歪吧卜
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name 歪比吧卜 | |
// @namespace https://taiho.moe/ | |
// @version 0.1.6 | |
// @description 比比比比吧歪比歪比比卜比歪比歪比比吧吧歪歪卜比比吧比吧歪歪吧吧吧卜比比歪比吧歪比比比歪卜比比歪比吧比吧比歪比卜比歪歪吧比比吧吧吧歪卜比歪歪吧歪吧比比歪比卜比歪比吧吧吧吧歪吧比卜比歪歪比比吧比比歪吧卜 | |
// @author swordfeng | |
// @match http://bgm.tv/group/* | |
// @match https://bgm.tv/group/* | |
// @match http://bangumi.tv/group/* | |
// @match https://bangumi.tv/group/* | |
// @match https://bgm.tv/subject/topic/* | |
// @exclude https://bgm.tv/group/new_group | |
// @grant none | |
// ==/UserScript== | |
// Original work: https://jiamitongxin.dovahkiin.top/ | |
function waibi(str) { | |
let len = str.length | |
let res = '' | |
const charWaibi =(c)=>{ | |
const dic=["歪","比","吧"] | |
let l = c.length | |
let r = "" | |
for(let i =0;i<l;i++){ | |
r += dic[c[i]] | |
} | |
return r | |
} | |
for(let i=0; i<len;i++){ | |
let tmp = str[i].charCodeAt(0).toString(3) | |
res += charWaibi(tmp) +"卜" | |
} | |
return res | |
} | |
function biwai(str) { | |
const charWaibi =(c)=>{ | |
const dic={"歪":"0","比":"1","吧":"2"} | |
let l = c.length | |
let r = "" | |
for(let i =0;i<l;i++){ | |
r += dic[c[i]] || "" | |
} | |
return r | |
} | |
let arr = str.split("卜") | |
arr.pop() | |
let res = arr.reduce((a,c)=>{ | |
if(c){ | |
let code = parseInt(charWaibi(c)||0,3) | |
return a + String.fromCharCode(code) | |
}else{ | |
return a | |
} | |
},'') | |
return res | |
} | |
function biwaiText(text) { | |
if (text.indexOf("卜") === -1) return null | |
let lspace = 0 | |
while (lspace < text.length && "歪比吧卜".indexOf(text[lspace]) === -1) lspace++ | |
if (lspace === text.length) return null | |
let rspace = 0 | |
while (rspace < text.length && "歪比吧卜".indexOf(text[text.length - 1 - rspace]) === -1) rspace++ | |
if (text.length - lspace - rspace < 5) return null | |
for (let c of text.slice(lspace, text.length - rspace)) { | |
if ("歪比吧卜".indexOf(c) === -1) return | |
} | |
text = text.slice(0, lspace) | |
+ biwai(text.slice(lspace, text.length - rspace)) | |
+ text.slice(text.length - rspace) | |
let tmpText = biwaiText(text) | |
if (tmpText) text = tmpText | |
return text | |
} | |
function biwaiNodesRec(node, depth) { | |
if (!depth) depth = 0 | |
if (depth > 3) { | |
// console.log(node) | |
return | |
} | |
if (node.noWaibi) return | |
if (node.nodeType === Node.TEXT_NODE) { | |
const decoded = biwaiText(node.nodeValue) | |
if (decoded) { | |
node.nodeValue = decoded | |
if (window.getComputedStyle(node.parentElement).whiteSpace === 'normal') { | |
node.parentNode.style.whiteSpace = 'pre-line' | |
} | |
const beginMark = document.createElement('sub') | |
beginMark.innerText = '<歪比>' | |
beginMark.style.opacity = 0.5 | |
beginMark.noWaibi = true | |
const endMark = document.createElement('sub') | |
endMark.innerText = '</吧卜>' | |
endMark.style.opacity = 0.5 | |
endMark.noWaibi = true | |
node.parentElement.insertBefore(beginMark, node) | |
node.parentElement.insertBefore(endMark, node.nextSibling) | |
} | |
} else if (node.nodeType === Node.ELEMENT_NODE) { | |
if (Array.prototype.indexOf.call(node.classList, 'cmt_sub_content') !== -1) { | |
// backup content to prevent deciphered replies | |
const backupNode = document.createElement('div') | |
backupNode.className = 'cmt_sub_content' | |
backupNode.style.display = 'none' | |
backupNode.innerHTML = node.innerHTML | |
backupNode.noWaibi = true | |
node.parentElement.insertBefore(backupNode, node) | |
} | |
for (let subNode of node.childNodes) { | |
biwaiNodesRec(subNode, depth + 1) | |
} | |
} | |
node.noWaibi = true | |
} | |
function translate(rootNode) { | |
for (let node of rootNode.getElementsByClassName('topic_content')) biwaiNodesRec(node) | |
for (let node of rootNode.getElementsByClassName('message')) biwaiNodesRec(node) | |
for (let node of rootNode.getElementsByClassName('cmt_sub_content')) biwaiNodesRec(node) | |
} | |
function parseTag(text, pos) { | |
if (text[pos] !== '[') return null | |
let r = pos + 1 | |
for (; r < text.length; r++) { | |
if (text[r] === '[') return null | |
if (text[r] === ']') break | |
} | |
if (r >= text.length || text[r] !== ']') return null | |
const tag = text.slice(pos, r + 1) | |
console.log('tag:', tag) | |
if (tag === '[b]' || | |
tag === '[/b]' || | |
tag === '[i]' || | |
tag === '[/i]' || | |
tag === '[u]' || | |
tag === '[/u]' || | |
tag === '[s]' || | |
tag === '[/s]' || | |
tag === '[mask]' || | |
tag === '[/mask]' || | |
tag.startsWith('[color=') || | |
tag === '[/color]' || | |
tag.startsWith('[size=') || | |
tag === '[/size]' || | |
tag.startsWith('[url=') || | |
tag === '[url]' || | |
tag === '[/url]' || | |
tag === '[img]' || | |
tag === '[/img]') { | |
return tag | |
} | |
return null | |
} | |
function parseEmoticon(text, pos) { | |
if (text.slice(pos, pos + 4) !== '(bgm') return null | |
let r = pos + 4 | |
while (r < text.length && text[r] >= '0' && text[r] <= '9') r++ | |
if (text[r] !== ')') return null | |
return text.slice(pos, r + 1) | |
} | |
function parseText(text) { | |
let pos = 0 | |
let result = [] | |
let current = '' | |
while (pos < text.length) { | |
if (text[pos] === '[') { | |
let tag = parseTag(text, pos) | |
if (tag) { | |
if (current.length) result.push({type: 'text', content: current}) | |
result.push({type: 'tag', content: tag}) | |
current = '' | |
pos += tag.length | |
continue | |
} | |
} | |
if (text[pos] === '(') { | |
let emoticon = parseEmoticon(text, pos) | |
if (emoticon) { | |
if (current.length) result.push({type: 'text', content: current}) | |
result.push({type: 'emoticon', content: emoticon}) | |
current = '' | |
pos += emoticon.length | |
continue | |
} | |
} | |
current += text[pos] | |
pos++ | |
} | |
if (current.length) result.push({type: 'text', content: current}) | |
return result | |
} | |
function waibiText(text) { | |
// console.log(text) | |
let parsed = parseText(text) | |
let pos = 0 | |
while (pos < parsed.length) { | |
if (parsed[pos].type === 'text') { | |
parsed[pos].content = waibi(parsed[pos].content) | |
pos++ | |
continue | |
} | |
if (parsed[pos].type === 'emoticon') { | |
pos++ | |
continue | |
} | |
if (parsed[pos].type === 'tag') { | |
if (parsed[pos].content === '[img]') { | |
pos += 2 // skip image url | |
continue | |
} | |
if (parsed[pos].content === '[url]') { | |
parsed[pos].content = '[url=' + parsed[pos + 1].content + ']' // inline url | |
} | |
pos++ | |
continue | |
} | |
// error | |
break | |
} | |
// console.log(parsed) | |
let resultText = '' | |
for (let item of parsed) resultText += item.content | |
return resultText | |
} | |
function addWaibi(rootNode) { | |
for (let node of rootNode.getElementsByClassName('inputBtn')) { | |
if (node.type !== 'submit') continue | |
let form = node | |
while (form && form.tagName !== 'FORM') form = form.parentElement | |
let waibiBtn = document.createElement('input') | |
waibiBtn.type = 'button' | |
waibiBtn.className = 'inputBtn' | |
waibiBtn.value = '歪比吧卜' | |
waibiBtn.addEventListener('click', () => { | |
let textarea = form.getElementsByTagName('textarea')[0] | |
if (!textarea) return | |
textarea.value = waibiText(textarea.value) | |
}) | |
node.parentElement.insertBefore(waibiBtn, node.nextSibling) | |
node.parentElement.insertBefore(document.createTextNode('\u00A0\u00A0'), node.nextSibling) | |
} | |
} | |
(function() { | |
'use strict'; | |
translate(document) | |
addWaibi(document) | |
new MutationObserver((mutlist, observer) => { | |
for (let mut of mutlist) { | |
if (mut.type !== 'childList') continue | |
for (let node of mut.addedNodes) { | |
if (node.nodeType !== Node.ELEMENT_NODE) continue | |
translate(node) | |
addWaibi(node) | |
} | |
} | |
}).observe(document.body, {childList: true, subtree: true}) | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment