Abstract Emoji encryptor

Fff**k.

目前為 2025-01-19 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Abstract Emoji encryptor
// @namespace    https://bgm.tv
// @version      1.0
// @description  Fff**k.
// @author       Rin
// @match        *://*/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @license      MIT
// ==/UserScript==
(function() {
    'use strict';
    const hostname=window.location.hostname;
    let settings = {
        promptTemplate: GM_getValue("promptTemplate", '你的好朋友是二次元婆罗门论坛bangumi上的动漫高手,阅番无数,无人能及,就连站长sai见了都要尊称一句性焦虑领域大神。依次使用下面给出的符号,编写一段话送给你的好朋友,请注意在合适的位置插入符号以保持它们的顺序。\n符号顺序为:'),//如果不存在则使用默认值
    };
    GM_registerMenuCommand('设置提示模板', function() {
        let promptTemplate = prompt("", settings.promptTemplate);
        if (promptTemplate) {
          GM_setValue("promptTemplate", promptTemplate);
          settings.promptTemplate=GM_getValue("promptTemplate", '你的好朋友是二次元婆罗门论坛bangumi上的动漫高手,阅番无数,无人能及,就连站长sai见了都要尊称一句性焦虑领域大神。依次使用下面给出的符号,编写一段话送给你的好朋友,请注意在合适的位置插入符号以保持它们的顺序。\n符号顺序为:');
        }
    });
    window.onerror = function(message, source, lineno, colno, error) {
      if(source.includes("Abstract%20Emoji%20encryptor"))
        alert(`Error:${error.message}`);
    }
    const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
    const createElement = (tag, props = {}, styles = {}) => {
        const el = Object.assign(document.createElement(tag), props);//创建元素
        Object.assign(el.style, styles);//配置styles
        return el;
    };
    const gbkDecoder = new TextDecoder('gb18030');//能解码gbk不支持的符号,比如欧元、表意文字
    const ranges = [
      [0xA1, 0xA9,  0xA1, 0xFE],
      [0xB0, 0xF7,  0xA1, 0xFE],
      [0x81, 0xA0,  0x40, 0xFE],//从这里开始的三个扩展区,第二个字节要排除0x7F
      [0xAA, 0xFE,  0x40, 0xA0],
      [0xA8, 0xA9,  0x40, 0xA0],
    ];
    const characterSet = ["~","?","………","⚡","⭐","😆","😗","👣","😨","🤓","🤣","😘‖","🥵","😉","🚀","😀","😋","😂","😅","😭","😇","🔥","😍","😡","😠","🤬","😈","👿","😤","💀","☠️","😻","😽","👹","👽","👻","👾","🤖","🤡","💩","🙊","🙉","🙈","💌","💘","💞","💕","💟","❣️","💔","❤️","💙","💚","💜","🖤","🤍","👁️‍🗨️","💤","💦","🕳️","💫","💥","💢","💯","💋","🎄","🎊","🎇","✨","🎈","🎉","🎁","🎀","🎐","🎃","🧧","🥇","🎖️","🏅","🏆","⚽","🏀","🥊","🤿","🎣","🪁","🎯","🎮","🔮","🎲","🧸","♥️","🎭","🎨","🧵","🧶","👓","🕶️","🥽","👔","👗","👘","🧣","🧤","🧦","🩲","🩱","👜","🎒","🩰","👙","👑","🎩","📿","💄","💍","💎","🔔","🔊","📣","📢","🎼","🎵","🎶","🎧","🎤","🎻","🎺","🥁","📱","📞","⌨️","💻","📷","📼","🎬","🏮","🕯️","🔎","💡","🔦","📕","📔","📖","📚","📜","💰","💵","💸","✉️","📧","📦","✏️","🖍️","🖌️","✒️","📝","📍","💼","📆","📈","📉","🗑️","🔑","🗝️","🔒","🔐","⚖️","🧲","🔗","🛡️","🏹","⚔️","🗡️","🔧","⚙️","🛠️","⛏️","🪓","🔨","💣","🧬","🔭","📡","💉","🩸","💊","🩹","🩺","🛏️","🚿","🚽","🛋️","🚪","🛁","🧹","🧻","🧽","🧼","🚬","⚰️","♿","🔞","🚫","⚠️","⛔","⬆️","➡️","🛐","✡️","✝️","🔁","▶️","◀️","⏩","⏫","♂️","♾️","❗","❕","❓","❔","‼️","⁉️","💲","✅","☑️","✔️","❌","❎","⭕","♻️","⚜️","➿","➰","🆒","🆕","🆚","🆗","🆘","🆙","🆓","ℹ️","🔴","⚫","⚪","🔷","🟥","⬛","⬜","💠","🔳","🚩","🏁","🏳️‍🌈","‍🏴‍☠️"];
    sort(hostname,characterSet);
    let codes,table;
    function encodeToGBK(str) {
      if(!codes){
        codes=new Uint16Array(22046);//先把全部gbk字符都保存到一个16位整型数组里
        let i = 0,t;
        for (const [b1Begin, b1End, b2Begin, b2End] of ranges) {
          for (let b2 = b2Begin; b2 <= b2End; b2++) {
            if (b2 !== 0x7F) {//反过来遍历,减少判断0x7F的次数
              t = b2 << 8; //不能用16位的codes[i]
              for (let b1 = b1Begin; b1 <= b1End; b1++)
                codes[i++] = t | b1;
            }
          }
        }
      }
      if(!table){
        table = new Uint16Array(65509);//gbk包含¤,小到164,将164左移到0也才省一点点空间
        const str = gbkDecoder.decode(codes);//解码为包含全部gbk字符的字符串
        for (let i = 0; i < str.length; i++){
          table[str.charCodeAt(i)] = codes[i];//unicode到gbk的映射
        }
      }
      const buf = new Uint8Array(str.length * 2);
      let n = 0;
      for (let i = 0; i < str.length; i++) {
        const code = str.charCodeAt(i);
        if (code < 128)
          buf[n++] = code;
        else{
              const gbk = table[code];
              if (gbk === 0)
                throw new Error("文本中存在不支持的符号");//有些编码器会用问号替换来避免报错,但这实际已经发生信息丢失了,不能容忍
              else {
                buf[n++] = gbk;
                buf[n++] = gbk >> 8;
              }
        }
      }
      return buf.subarray(0, n);
    }

    async function encode(str) {
        let result = '';
        let data= encodeToGBK(str);
        await sort(hostname,data);
        for (let b of data) {
            result += characterSet[b & 0xFF] + '  ';
        }
        return result.trimEnd();
    }
    async function encrypt() {
        const userInput = prompt("🔒(可在扩展管理界面设置提示模板)");
        if(userInput){
          const emoji=await encode(userInput);
          if(isMobile)
            alert(`成功!Emoji:${settings.promptTemplate}${emoji}`);
          else {
            await navigator.clipboard.writeText(settings.promptTemplate+emoji);
            alert('成功!Emoji已复制到剪切板');
          }
        }

    }
    async function decrypt() {
      const userInput = prompt("🗝️");
      if(userInput){
        let list = [];
        let maxCharLength = 7;
        for (let i = 0; i < userInput.length; i++) {
          for (let j = maxCharLength; j >= 1; j--) {
            if (i + j <= userInput.length) {
              let subString = userInput.substring(i, i + j);
              let index = characterSet.indexOf(subString);
              if (index !== -1) {
                list.push(index);
                i += j - 1;
                break;
              }
            }
          }
        }
        const origin=new Uint8Array(list);
        await resort(hostname,origin);
        alert(gbkDecoder.decode(origin));
      }
    }
    async function sort(obfuscator,target) {
      const msgUint8 = new TextEncoder().encode(obfuscator); // 编码为 Uint8Array
      const hashBuffer = await crypto.subtle.digest('SHA-512', msgUint8);//哪怕可以基于target长度使用位数更少的sha256,但是解码的时候对于targer长度是不确定的
      const uint8Array = new Uint8Array(hashBuffer);
      const bitArray=new Uint8Array(512);let k=0;
      for (let i = 0; i < uint8Array.length; i++) {
        const byte = uint8Array[i];
        for (let j = 7; j >= 0; j--) // 从高位到低位遍历每个比特
          bitArray[k++]=(byte >> j) & 1;
      }
      for(let i=0;i<target.length-2;i++)
        if(bitArray[i]===1){
          const t=target[i];
          target[i]=target[i+1];
          target[i+1]=t;
        }
        else{
          const t=target[i];
          target[i]=target[i+2];
          target[i+2]=t;
        }
    }
    async function resort(obfuscator,target){
      const msgUint8 = new TextEncoder().encode(obfuscator); // 编码为 Uint8Array
      const hashBuffer = await crypto.subtle.digest('SHA-512', msgUint8);//哪怕可以基于target长度使用位数更少的sha256,但是解码的时候对于targer长度是不确定的
      const uint8Array = new Uint8Array(hashBuffer);
      const bitArray=new Uint8Array(512);let k=0;
      for (let i = 0; i < uint8Array.length; i++) {
        const byte = uint8Array[i];
        for (let j = 7; j >= 0; j--) // 从高位到低位遍历每个比特
          bitArray[k++]=(byte >> j) & 1;
      }
      for(let i=target.length-3;i>=0;i--)
          if(bitArray[i]===1){
            const t=target[i];
            target[i]=target[i+1];
            target[i+1]=t;
          }
          else{
            const t=target[i];
            target[i]=target[i+2];
            target[i+2]=t;
          }
    }
    function swapColors(){
      let t=sidebarButton1.style.backgroundColor;
      sidebarButton1.style.backgroundColor=sidebarButton2.style.backgroundColor;
      sidebarButton2.style.backgroundColor=t;
    }
    const buttonStyles1 = {
      position: 'fixed',
      right: '0', //固定右侧
      zIndex: '9999', // 确保不被覆盖
      cursor: 'pointer',//显示可点击光标
      backgroundColor:'#f56c73',
      border: 'none',
      top:   '42%',
      height: '25px',
      width: '25px',
      overflow: 'hidden',
    };
    const buttonStyles2 = {
        position: 'fixed',
        right: '0', //固定右侧
        zIndex: '9999', // 确保不被覆盖
        cursor: 'pointer',//显示可点击光标
        backgroundColor:'#d87b83',
        border: 'none',
        top:   '47%',
        height: '25px',
        width: '25px',
        overflow: 'hidden',
      };
    const sidebarButton1 = createElement('button', {}, buttonStyles1);
    const sidebarButton2 = createElement('button', {}, buttonStyles2);
    sidebarButton1.addEventListener('mouseenter', () => swapColors() );
    sidebarButton2.addEventListener('mouseenter', () => swapColors() );
    sidebarButton1.addEventListener('click', () => encrypt());
    sidebarButton2.addEventListener('click', () => decrypt());
    document.body.append(sidebarButton1, sidebarButton2);
})();