清水河畔表情包计划

请自己研究尝试

目前为 2022-10-08 提交的版本。查看 最新版本

// ==UserScript==
// @name         清水河畔表情包计划
// @namespace    http://tampermonkey.net/
// @version      0.1.5.5
// @description  请自己研究尝试
// @author       DARK-FLAME-MASTER FROM RIVERSIDE
// @match        https://bbs.uestc.edu.cn/forum.php?mod=viewthread*
// @Match        *://bbs-uestc-edu-cn-s.vpn.uestc.edu.cn:*/forum.php?mod=viewthread*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=uestc.edu.cn
// @require      https://cdn.jsdelivr.net/npm/[email protected]/cfb.js
// @require      https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.js
// @license      WTFPL
// @run-at       document-idle
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_listValues
// @grant        unsafeWindow
// ==/UserScript==

(function () {
    'use strict';


    function notice_emoji(text) {
      Notification.requestPermission().then((result) => { if (result === 'granted') { let n = new Notification(text); setTimeout(n.close.bind(n), 1800) } })
    }

    function listFiles(src, allowed_exts = []) {
      let f = new FileReader()
      let group_name = src[0].name
      f.readAsBinaryString(src[0]);
      let file_list = [];
      f.onload = function () {
        let eif = CFB.read(this.result, { type: 'binary' })
        let valid_paths = []
        let valid_content = eif.FileIndex.filter((e, i) => {
          if (e.size > 0) {
            valid_paths.push(eif.FullPaths[i])
            return true
          }
          return false
        })

        let s = new Set()
        let file_list_upload = {}
        for (let idx in valid_content) {
          let entry = valid_content[idx]
          let extname = entry.name.substring(entry.name.lastIndexOf(".") + 1)
          if (entry.type == 2 && (!allowed_exts || _.indexOf(allowed_exts, extname) >= 0)) {
            let name = valid_paths[idx].substring(0, valid_paths[idx].lastIndexOf("."))
            if (!s.has(name)) {
              let group = valid_paths[idx].match(/Entry\/(\d+)\//)[1]
              upload_count += 1
              let f = new File([new Uint8Array(entry.content)], entry.name, { type: "image/" + extname })
              if (file_list_upload[group]) {
                file_list_upload[group].push(f)
              } else {
                file_list_upload[group] = [f]
              }
              s.add(name + 'fix')
            }

          }
        }

        for (let group in file_list_upload) {
          upload_emoji(file_list_upload[group], group_name + group)
        }
        document.getElementById('progress_upload').hidden = false
        document.getElementById('progress_upload').max = upload_count

      }
    }

    function add_emoji(id, src, flag = true, group = 'default') {
      return function () {
        if (group == 'default') group = selected_group.group
        if (!emoji_set[group]) emoji_set[group] = []
        emoji_set[group].push([id + 'e', src])
        GM_setValue('emoji_set', emoji_set)
        group = 'default'
        if (flag == true)
          notice_emoji('已添加表情')

      }
    }
    function del_emoji(id, group = 'default') {
      return function () {
        let e = document.getElementById(id)
        e.parentNode.removeChild(e)
        emoji_set[group] = emoji_set[group].filter((c, i, s) => c[0] != id)
        if (emoji_set[group] == 0) del_group(group)
        GM_setValue('emoji_set', emoji_set)
        notice_emoji('已删除表情')
      }

    }

    function del_group(group) {
      return function () {
        let msg = "您确定要删除该分组吗?";
        if (confirm(msg) == true && emoji_group_list.length > 1) {
          let e = document.getElementById(group)
          e.parentNode.removeChild(e)
          delete emoji_set[group]
          if (selected_group.group == group) {
            let ind = emoji_group_list.indexOf(group)
            emoji_group_list.splice(ind, 1)
            if (ind != 0)
              selected_group.group = emoji_group_list[ind - 1]
            else
              selected_group.group = emoji_group_list[0]
          }
          GM_setValue('emoji_set', emoji_set)
          notice_emoji('已删除分组')
        }
      }
    }

    function addCss(styleCss) {
      let head = document.querySelector('head');
      let style = document.createElement('style');
      style.type = 'text/css';
      let text = document.createTextNode(styleCss);
      style.appendChild(text)
      head.appendChild(style);
    }

    function upload_eif(input) {
      listFiles(input.target.files, ['jpg', 'gif', 'bmp', 'png'])
    }

    function upload_emoji_select(input) {
      upload_emoji(input.target.files)
    }

    function upload_emoji(input, group = 'default') {
      [].forEach.call(input, function (file) {
        file = {
          name: file.name,
          size: file.size,
          type: file.type,
          dom: file,
        };
        let data = new FormData();
        for (let k in post_params)
          data.append(k, post_params[k]);
        data.append('type', 'image')
        data.append('filetype', file.type)
        data.append('Filename', file.name);
        data.append('Filedata', file.dom);
        let pid;
        fetch("/misc.php?mod=swfupload&action=swfupload&operation=album", {
          "headers": {
          },
          "method": "POST",
          "mode": "cors",
          "body": data,
          "credentials": "include",
        }).then((res) => res.json()).then((data) => {

          pid = data.picid;
          add_emoji(pid, data.bigimg, false, group)();
          return fetch("/home.php?mod=spacecp&ac=upload", {
            "headers": {
              "content-type": "application/x-www-form-urlencoded",
            },
            "body": "title[" + pid + "]=&albumid="+emoji_album_id+"&albumsubmit=true&albumsubmit_btn=true&formhash=" + formhash,
            "method": "POST",
            "mode": "cors",
            "credentials": "include"
          })
        }).then((data) => { upload_count -= 1; let p = document.getElementById('progress_upload'); p.value = p.max - upload_count; if (upload_count == 0) notice_emoji('已上传完毕') })


      }
      )
    }

    function switch_tag(e) {
      let id = e.currentTarget.id
      selected_group.group = id
      unsafeWindow.setMenuPosition('mine','mine_menu','12!')
    }

    function update_emoji() {
      let emoji_in_group = emoji_set[selected_group.group]
      let emoji_data = '<div id = "group" style ="display:flex; flex-wrap: wrap; justify-content: space-evenly;align-items: center;"><input id ="upload" type="file" accept=".jpg;.jpeg;.gif;.png" multiple style="display: none;  " ><div id ="add_emoji" style="        font-size: 40px;line-height: 109%;margin-right: 5px;" class = clicked onclick = "$(\'upload\').click();">➕</div>'
      document.getElementById('append_parent').innerHTML =''

      for (let i = 0; i < emoji_in_group.length; ++i) {
        let emoji_id = emoji_in_group[i][0]
        src = emoji_in_group[i][1]


        emoji_data += '<div id="' + emoji_id + '" class = clicked  onclick="seditor_insertunit(' + (document.getElementById('postat') != null ? '\'post\'' : '\'fastpost\'') + ',\'[img]' + src + '[/img]\')" onmouseover="showMenu({\'ctrlid\':this.id,\'pos\':\'21!\',\'layer\':3})"><img  height="50" class = emoji src="' + src + '" /></div>'
        let div = document.createElement('div');
        div.id = emoji_id + '_menu';
        div.aid = emoji_id;
        div.style = 'margin-top : 17px;display:none';
        div.addEventListener('click', del_emoji(div.aid, selected_group.group));
        div.innerHTML = "❎";
        document.getElementById('append_parent').appendChild(div);
      }
      emoji_data += '</div>'
      document.getElementById('emo_content').innerHTML = emoji_data

      document.getElementById('upload').addEventListener('change', upload_emoji_select.bind(document.getElementById('upload')))
      let emo_tag = document.getElementById('emo_tag')
      emo_tag.innerHTML = ''
      for (let emoji_group in emoji_set) {
        let d = document.createElement('div')
        d.id = emoji_group
        let img = document.createElement('img')
        d.classList = ['tag clicked'];
        img.src = (emoji_set[emoji_group].length> 0) ? (emoji_set[emoji_group][0][1]) : " ";
        d.innerHTML = img.outerHTML;
        d.addEventListener('click', switch_tag)
        d.setAttribute("onmouseover", "showMenu({\'ctrlid\':this.id,\'pos\':\'21!\',\'layer\':3})")
        emo_tag.appendChild(d)
        let div = document.createElement('div');
        div.id = emoji_group + '_menu';
        div.aid = emoji_group;
        div.style = 'margin-top : 17px;display:none';
        div.addEventListener('click', del_group(div.aid));
        div.innerHTML = "❎";
        document.getElementById('append_parent').appendChild(div);

      }
      document.getElementById(selected_group.group).classList.add('selected')
              unsafeWindow.smilies_show('fastpostsmiliesdiv', 8, 'fastpost')

    }

    function init_emoji(emoji_set) {
      document.querySelectorAll('.xs0>p:nth-child(2)').forEach((ele) => { let b = document.createElement("a"); b.innerHTML = '添加至表情包'; b.classList = ['clicked']; b.addEventListener('click', add_emoji(ele.parentNode.parentNode.previousElementSibling.id, ele.parentNode.parentNode.previousElementSibling.src)); ele.appendChild(b) })
      document.querySelectorAll('.t_f>img.zoom').forEach((ele) => {
        let div = document.createElement('div');
        div.innerHTML = "➕";
        div.style = 'position: absolute;top: 0;  display:none';
        div.addEventListener('click', add_emoji(ele.id, ele.getAttribute('file')));
        let p = ele.parentElement; p.removeChild(ele);
        let new_div = document.createElement('div');
        new_div.addEventListener("mouseover", () => { div.style.display = "block"; div.style.fontSize = Math.ceil(ele.width * 0.15) + 'px'; });
        new_div.addEventListener("mouseout", () => div.style.display = "none");
        new_div.style = "position :relative";
        new_div.appendChild(div);
        new_div.appendChild(ele);
        p.appendChild(new_div);
      })


      let emo = document.createElement("a");
      emo.id = "mine"
      emo.style = " background-image: url(\"data:image/svg+xml,%3Csvg width='20' height='20' xmlns='http://www.w3.org/2000/svg'%3E%3Ctext x='' y='15' font-size='12' %3E%F0%9F%98%80%3C/text%3E%3C/svg%3E\")"
      emo.classList = ['clicked']
      emo.setAttribute('onclick', "if(!$(mine_menu.display)) {showMenu({'ctrlid':this.id,'evt':'click','pos':'12',\'duration\':3,\'drag\':1});$(mine_menu).style.overflow = '';}else{hideMenu();}")

      let emo_menu = document.createElement('div')
      emo_menu.id = "mine_menu"
      emo_menu.style = "display: none;padding: 3px 3px 0 0;    background: rgb(232, 241, 252);    border: 2px solid lightsteelblue;    border-radius: 5px;    width: 50%"

      let emo_tag = document.createElement('div')
      emo_tag.id = "emo_tag"
      emo_tag.style = "display: flex;height: 45px;background-color: lightsteelblue;align-items: center;width: fit-content;border-radius: 0 0 4px 0;border: 0px solid lightsteelblue"
      let emo_content = document.createElement('div')
      emo_content.id = "emo_content"
      emo_content.style = "overflow:auto auto;max-height:400px"


      for (let emoji_group in emoji_set) {
        let d = document.createElement('div')
        d.id = emoji_group
        let img = document.createElement('img')
        d.classList = ['tag clicked'];
        img.src = (emoji_set[emoji_group].length != 0) ? (emoji_set[emoji_group][0][1]) : " ";
        d.innerHTML = img.outerHTML;
        d.addEventListener('click', switch_tag)
        emo_tag.appendChild(d)


      }
        emo_menu.appendChild(emo_content)
      emo_menu.appendChild(emo_tag)

      let emo_fast = emo.cloneNode(true)
      setInterval(() => { document.getElementById('postat') != null ? document.getElementById('postat').insertAdjacentElement('beforebegin', emo_fast) : "" }, 1000)


      document.getElementById('fastpostat').insertAdjacentElement('beforebegin', emo)
      document.getElementById('fastpostat').insertAdjacentElement('beforebegin', emo_menu);
      update_emoji(emoji_set[selected_group.group])



      addCss('img.emoji {padding: 2px;border-radius: 10px;} .clicked:hover {cursor: pointer;} div.tag {    height: 45px;    padding: 0 3px 0 3px;    border-radius: 2px;    display: flex;    align-items: center;} div.tag > img {    height: 30px;    border-radius: 2px;} .selected {    background: rgb(232, 241, 252);}')


      let i = document.createElement('input')
      i.type = 'file'
      i.accept = ".eif"
      i.addEventListener('change', upload_eif.bind(i))
      document.querySelector("#post_replytmp").parentNode.appendChild(i)
      document.getElementById(selected_group.group).classList += ' selected'
      let p = document.createElement('progress')
      p.id = 'progress_upload'
      p.value = 0
      p.hidden = true
      p.innerHTML = "进度"
      document.querySelector("#post_replytmp").parentNode.appendChild(p)
    }
    //GM_deleteValue('emoji_set')
    //GM_deleteValue('emoji_album_id')
    //GM_setValue('default_group','mine.eif8213')
    let upload_count = 0
    let version = GM_getValue('version', 'NULL')
    if(version ==  'NULL')
    {
        GM_deleteValue('emoji_set')
        GM_deleteValue('emoji_album_id')
        GM_setValue('version', '0.1.5.1')
    }
    let post_params = unsafeWindow.upload.settings.post_params;
    let formhash = document.getElementById('modactions').childNodes[1].value;
    let emoji_set = GM_getValue('emoji_set', { 'default': [] })
    let emoji_group_list = []
    let emoji_album_id = GM_getValue('emoji_album_id', 'NULL')
    if (emoji_album_id == 'NULL') {
      let i = document.createElement('button')
      i.innerHTML = '初始化'
      document.querySelector("#post_replytmp").parentNode.appendChild(i)
      i.addEventListener('click',()=>{emoji_album_id=prompt("请输入表情保存的相册ID:");if(emoji_album_id!=null){ GM_setValue('emoji_album_id',emoji_album_id);i.style.display="None";notice_emoji("初始化成功")}})
    }
    for (let emoji_group in emoji_set) {
      emoji_group_list.push(emoji_group)
    }
    let _selected_group = GM_getValue('default_group', 'default')
    let selected_group = {}
    Object.defineProperty(selected_group, 'group', {
      configurable: true,
      get: function () {
        return _selected_group;
      },
      set: function (value) {
        if (document.getElementById(_selected_group) != null) document.getElementById(_selected_group).classList.toggle('selected')
        _selected_group = value;
        update_emoji()
        GM_setValue('default_group', _selected_group)
      }
    })
    console.log(emoji_set)
    init_emoji(emoji_set);
    setInterval("setMenuPosition('mine','mine_menu','12!')",1000)
    setInterval(update_emoji, 3000)
  })();