清水河畔表情包计划

请自己研究尝试

目前為 2022-10-06 提交的版本,檢視 最新版本

// ==UserScript==
// @name         清水河畔表情包计划
// @namespace    http://tampermonkey.net/
// @version      0.1.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("https://bbs.uestc.edu.cn/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("https://bbs.uestc.edu.cn/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
  }

  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>'
    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')

  }

  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':'23',\'duration\':3,\'drag\':1,\'maxh\':400});}else{hideMenu();}")

    let emo_menu = document.createElement('div')
    emo_menu.id = "mine_menu"
    emo_menu.style = "display: none;overflow: hidden;padding: 0 3px 3px 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_cotent = document.createElement('div')
    emo_cotent.id = "emo_content"



    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_tag)
    emo_menu.appendChild(emo_cotent)
    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 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(update_emoji, 3000)
})();