// ==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)
})();