Skip to content

Instantly share code, notes, and snippets.

@swordfeng
Last active June 30, 2021 16:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save swordfeng/749f68a675a10baa597f52b7d65adc57 to your computer and use it in GitHub Desktop.
Save swordfeng/749f68a675a10baa597f52b7d65adc57 to your computer and use it in GitHub Desktop.
比比比比吧歪比歪比比卜比歪比歪比比吧吧歪歪卜比比吧比吧歪歪吧吧吧卜比比歪比吧歪比比比歪卜比比歪比吧比吧比歪比卜比歪歪吧比比吧吧吧歪卜比歪歪吧歪吧比比歪比卜比歪比吧吧吧吧歪吧比卜比歪歪比比吧比比歪吧卜
// ==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