// ==UserScript==
// @name 动漫花园屏蔽评论
// @namespace https://greasyfork.org/zh-CN/users/171607
// @version 0.2
// @description 实现可分别按用户名、关键字、正则表达式对评论进行屏蔽; 鼠标移至网页右下角弹出悬浮按钮
// @author 菜姬
// @match *://dmhy.org/*
// @match *://www.dmhy.org/*
// @match *://share.dmhy.org/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_setClipboard
// @grant GM_registerMenuCommand
// ==/UserScript==
(function () {
'use strict';
const OLD_URL = location.href;
const CHECKBOX_VALUE = {
START: ['startCheckbox', '启用屏蔽功能', '总开关'],
VIDEO_USERNAME: ['videoUsernameCheckbox', '按用户名', '屏蔽指定用户发布的视频'],
VIDEO_KEYWORD: ['videoKeywordCheckbox', '按关键字', '屏蔽标题中包含指定关键字的视频'],
VIDEO_REG: ['videoRegCheckbox', '按正则', '屏蔽标题匹配指定正则表达式的视频'],
COMMENT_USERNAME: ['commentUsernameCheckbox', '按用户名', '屏蔽指定用户发布的评论'],
COMMENT_KEYWORD: ['commentKeywordCheckbox', '按关键字', '屏蔽内容中包含指定关键字的评论'],
COMMENT_REG: ['commentRegCheckbox', '按正则', '屏蔽内容匹配指定正则表达式的评论'],
CONVERT_EMOJI: ['convertEmojiCheckbox', '表情转成文字', '判定时将表情包转换成对应的标识文字,例:[doge]']
};
const INPUT_VALUE = {
USERNAME: ['usernameInput', '输入:', '多个时以半角逗号分隔'],
VIDEO_KEYWORD: ['videoKeywordInput', '输入:', '多个时以半角逗号分隔'],
COMMENT_KEYWORD: ['commentKeywordInput', '输入:', '多个时以半角逗号分隔'],
VIDEO_REG: ['videoRegInput', '输入:', ' / 建议写成 \\/ '],
VIDEO_MODIFIER: ['videoModifierInput', '修饰符:', '如:gim'],
COMMENT_REG: ['commentRegInput', '输入:', ' / 建议写成 \\/ '],
COMMENT_MODIFIER: ['commentModifierInput', '修饰符:', '如:gim']
};
const TEXTAREA_VALUE = {
USERNAME: ['usernameTextarea', ''],
VIDEO_KEYWORD: ['videoKeywordTextarea', ''],
COMMENT_KEYWORD: ['commentKeywordTextarea', ''],
VIDEO_REG: ['videoRegTextarea', ''],
COMMENT_REG: ['commentRegTextarea', '']
};
const BUTTON_VALUE = {
ADD: ['input_btn', '添加', '添加内容到列表中'],
DELETE: ['input_btn', '删除', '从列表中删除符合的项目'],
CLEAR: ['input_btn', '清空', '添空列表'],
COPY: ['input_btn', '复制', '复制列表'],
CANCEL: ['user_block_button cancel_button', '取消', '关闭设置窗口'],
SAVE: ['user_block_button save_button', '保存并关闭', '保存设置并关闭设置窗口'],
ONLY_SAVE: ['user_block_button save_button', '仅保存', '仅保存设置']
};
const STYLE_VALUE = `
.expand_box {
bottom: 0px;
height: 6vh;
position: fixed;
right: -6vw;
transition: 0.5s;
width: 12vw;
z-index: 99999;
}
.show_expand_box {
right: 0;
width: 6vw;
}
#expandSpan {
background-color: #00A1D6;
border-radius: 19px;
border: 1px solid #00A1D6;
bottom: 1vh;
color: #FFF;
cursor: pointer;
display: block;
font-size: 13px;
height: 38px;
line-height: 38px;
position: absolute;
right: 1vw;
text-align: center;
width: 38px;
z-index: 99999;
}
#wrapDiv {
background-color: #222222;
border-radius: 3px;
border: 1px solid #282A36;
bottom: 6vh;
box-shadow: 0 0 5px #282A36;
color: #D3D3D3;
font-size: 13px;
margin: 0px;
padding: 0px;
position: fixed;
text-align: left;
transition: 0.8s;
width: 452px;
z-index: 99999;
}
.show_wrap {
display: block;
right: 0;
}
.hide_wrap {
right: -460px;
}
#mainTag {
border-radius: 3px;
border: 3px groove #00A1D6;
height: auto;
margin: 8px;
min-width: 300px;
padding: 4px 9px 6px 9px;
width: auto;
}
.ul_tag {
list-style: none;
padding-left: 0;
}
.checkbox_li {
display: inline-block;
}
.move_right {
margin-left: 15px;
}
.checkbox_label {
cursor: pointer;
vertical-align: middle;
}
.checkbox_input {
clip: rect(0, 0, 0, 0);
position: absolute;
}
.checkbox_input + label::before {
background-color: silver;
border-radius: 0.1em;
color: #FFF;
content: "\\a0";
display: inline-block;
height: 1em;
line-height: 85%;
margin-right: 0.5em;
text-align: center;
vertical-align: 0.2em;
width: 1em;
}
.checkbox_input:checked + label::before {
background-color: #00A1D6;
content: "\\2713";
}
.separator_text {
color: #FFB86C;
margin-bottom: 2px;
margin-top: 2px;
}
.separator_symbol {
background-color: #303030;
height: 2px;
margin-bottom: 5px;
margin-top: 5px;
min-width: 400px;
}
.input_div {
margin-top: 5px;
}
.user_block_input {
background-color: #C0C0C0;
border: 1px solid #C0C0C0;
color: #000;
font-size: 13px;
height: 15px;
margin-left: 5px;
margin-right: 5px;
padding-left: 4px;
}
.input_btn {
background-color: #3da9cc;
border-radius: 3px;
border: 1px solid #73C9E5;
box-shadow: 0 0 4px #73C9E5;
color: #FFF;
cursor: pointer;
display: inline-block;
height: 15px;
line-height: 15px;
margin-left: 5px;
text-align: center;
vertical-align: bottom;
white-space: nowrap;
width: 30px;
}
.textarea_div {
margin-top: 5px;
}
.textarea_list_div {
border: 1px dotted #00A1D6;
margin-top: 3px;
max-height: 60px;
min-height: 3px;
overflow: auto;
}
.textarea_list_div::-webkit-scrollbar {
background-color: #555;
border-radius: 5px;
width: 10px;
}
.textarea_list_div::-webkit-scrollbar-thumb {
background-color: #333;
border-radius: 5px;
}
.textarea_copied {
color: #000;
}
.keyword_input {
width: 150px;
}
.reg_input {
width: 100px;
}
.modifier_input {
width: 50px;
}
.child_span {
background-color: #3D3D3D;
border-radius: 5px;
border: 1px solid #3D3D3D;
display: inline-block;
margin: 3px;
padding: 2px;
}
.child_text {
border-right: 1px solid #A9181C;
margin-right: 4px;
padding-right: 4px;
}
.child_del {
color: #A9181C;
cursor: pointer;
}
.user_block_button {
background-color: #FB7299;
border-radius: 4px;
border: 1px solid #FB7299;
color: #FFF;
cursor: pointer;
margin-top: 5px;
padding: 2px 4px;
position: relative;
}
.save_button {
float: right;
margin-right: 5px;
}
.cancel_button {
float: left;
margin-left: 5px;
}
.block_none {
display: none !important;
}
.block_hidden {
visibility: hidden;
}
`;
var dmhy_ban_config = {
usernameArray: [],
commentArray: [],
commentRegArray: []
};
var reg_config = {
regArray: [],
commentRegArray: []
};
function string_2_Array(text_string) {
let temp_array = text_string.split(',');
let return_array = [];
for (let i = 0, l = temp_array.length; i < l; i++) {
for (let j = i + 1; j < l; j++) {
if (temp_array[i] === temp_array[j]) {
++i;
j = i
}
}
return_array.push(temp_array[i])
}
return return_array
}
function array_2_String(text_array) {
return text_array.join(',')
}
function convert_Array(string_array) {
let re_arr = [];
for (let i = 0; i < string_array.length; i++) {
if (string_array[i]) {
try {
let new_reg = new RegExp(string_array[i].replace(/^\/|\/[a-z]*$/gi, ''), string_array[i].replace(/^\/.*\/[^a-z]*/i, ''));
re_arr.push(new_reg)
} catch (e) {
console.log('The transformation contains invalid regular expressions.');
console.log(e)
}
}
}
return re_arr
}
function extract_Array(list_id) {
let re_arr = [];
let list_dom = document.getElementById(list_id);
let list_arr = list_dom.getElementsByClassName('DmhyTextSpan');
for (let i = list_arr.length - 1; i >= 0; i--) {
if (list_arr[i].title) {
re_arr.push(list_arr[i].title)
} else {
re_arr.push(list_arr[i].innerText)
}
}
return re_arr
}
function del_Child(input_tag, list_id) {
let text_value = input_tag.value;
if (text_value) {
let del_status = false;
let text_arr = string_2_Array(text_value);
let save_arr = extract_Array(list_id);
text_arr.forEach(function (item) {
if (save_arr.includes(item)) {
let total_child = document.getElementById(list_id).getElementsByClassName('child_span');
try {
document.getElementById(list_id).removeChild(total_child[total_child.length - 1 - save_arr.indexOf(item)]);
del_status = true
} catch (e) {
del_status = false;
console.log('Error deleting element.');
console.log(e)
}
}
});
if (del_status) {
input_tag.value = ''
}
}
}
function add_Child(input_tag, list_id) {
let text_value = input_tag.value;
if (text_value) {
let text_arr = string_2_Array(text_value);
let save_arr = extract_Array(list_id);
text_arr.forEach(function (item) {
if (!save_arr.includes(item)) {
document.getElementById(list_id).insertAdjacentElement('afterbegin', create_Child(item))
}
})
}
input_tag.value = ''
}
function del_Reg_Child(reg_input, modifier_input, list_id) {
let reg_value = reg_input.value;
let modifier_value = modifier_input.value;
if (reg_value) {
let del_status = false;
try {
let reg_str = new RegExp(reg_value, modifier_value);
let save_arr = extract_Array(list_id);
if (save_arr.includes(reg_str.toString())) {
let total_child = document.getElementById(list_id).getElementsByClassName('child_span');
document.getElementById(list_id).removeChild(total_child[total_child.length - 1 - save_arr.indexOf(reg_str.toString())]);
del_status = true
}
} catch (e) {
del_status = false;
console.log('Invalid regular expression or error deleting element.');
console.log(e)
}
if (del_status) {
reg_input.value = '';
modifier_input.value = ''
}
}
}
function add_Reg_Child(reg_input, modifier_input, list_id) {
let reg_value = reg_input.value;
let modifier_value = modifier_input.value;
if (reg_value) {
try {
let reg_str = new RegExp(reg_value, modifier_value);
let save_arr = extract_Array(list_id);
if (!save_arr.includes(reg_str.toString())) {
document.getElementById(list_id).insertAdjacentElement('afterbegin', create_Child(reg_str.toString()))
}
reg_input.value = '';
modifier_input.value = ''
} catch (e) {
console.log('Invalid regular expression.');
console.log(e)
}
}
}
function expand_Wrap(id_value) {
if (document.getElementById(id_value)) {
if (document.getElementById(id_value).className == 'show_wrap') {
document.getElementById(id_value).className = 'hide_wrap'
} else {
document.getElementById(id_value).className = 'show_wrap'
}
} else {
create_Settings()
}
}
function insert_Separator(ul_node, text_value = '') {
let temp_li = document.createElement('li');
let temp_div = document.createElement('div');
if (text_value) {
temp_div.className = 'separator_text';
temp_div.innerText = text_value
} else {
temp_div.className = 'separator_symbol'
}
temp_li.appendChild(temp_div);
ul_node.appendChild(temp_li)
}
function insert_Checkbox(ul_node, li_array, check_enable_value, margin_status = true) {
let temp_li = document.createElement('li');
temp_li.className = 'checkbox_li';
if (margin_status) {
temp_li.classList.add('move_right')
}
let temp_input = document.createElement('input');
temp_input.type = 'checkbox';
temp_input.className = 'checkbox_input';
temp_input.id = li_array[0];
if (check_enable_value) {
temp_input.checked = true
} else {
temp_input.checked = false
}
let temp_label = document.createElement('label');
temp_label.className = 'checkbox_label';
temp_label.setAttribute('for', li_array[0]);
temp_label.innerText = li_array[1];
temp_label.title = li_array[2];
temp_li.appendChild(temp_input);
temp_li.appendChild(temp_label);
ul_node.appendChild(temp_li)
}
function insert_Input(ul_node, li_array, list_id) {
let temp_li = document.createElement('li');
let temp_div = document.createElement('div');
temp_div.className = 'input_div';
temp_div.innerText = li_array[1];
let temp_input = document.createElement('input');
temp_input.id = li_array[0];
temp_input.placeholder = li_array[2];
temp_input.type = 'text';
temp_input.className = 'user_block_input keyword_input';
temp_input.addEventListener('keyup', function (e) {
if (e.keyCode === 13) {
add_Child(temp_input, list_id)
}
});
let add_btn = create_Span_Btn(BUTTON_VALUE.ADD, function () {
add_Child(temp_input, list_id)
});
let delete_btn = create_Span_Btn(BUTTON_VALUE.DELETE, function () {
del_Child(temp_input, list_id)
});
let clear_btn = create_Span_Btn(BUTTON_VALUE.CLEAR, function () {
document.getElementById(list_id).innerHTML = ''
});
let copy_btn = create_Span_Btn(BUTTON_VALUE.COPY, function () {
GM_setClipboard(array_2_String(extract_Array(list_id)));
copy_btn.classList.add('textarea_copied');
copy_btn.title = '复制完成'
});
temp_div.appendChild(temp_input);
temp_div.appendChild(add_btn);
temp_div.appendChild(delete_btn);
temp_div.appendChild(clear_btn);
temp_div.appendChild(copy_btn);
temp_li.appendChild(temp_div);
ul_node.appendChild(temp_li)
}
function insert_Reg_Input(ul_node, reg_array, modifier_array, list_id) {
let temp_li = document.createElement('li');
let temp_div = document.createElement('div');
temp_div.className = 'input_div';
let reg_span = document.createElement('span');
reg_span.innerText = reg_array[1];
let reg_input = document.createElement('input');
reg_input.id = reg_array[0];
reg_input.placeholder = reg_array[2];
reg_input.type = 'text';
reg_input.className = 'user_block_input reg_input';
let modifier_span = document.createElement('span');
modifier_span.innerText = modifier_array[1];
let modifier_input = document.createElement('input');
modifier_input.id = modifier_array[0];
modifier_input.placeholder = modifier_array[2];
modifier_input.type = 'text';
modifier_input.className = 'user_block_input modifier_input';
let add_btn = create_Span_Btn(BUTTON_VALUE.ADD, function () {
add_Reg_Child(reg_input, modifier_input, list_id)
});
let delete_btn = create_Span_Btn(BUTTON_VALUE.DELETE, function () {
del_Reg_Child(reg_input, modifier_input, list_id)
});
let clear_btn = create_Span_Btn(BUTTON_VALUE.CLEAR, function () {
document.getElementById(list_id).innerHTML = ''
});
let copy_btn = create_Span_Btn(BUTTON_VALUE.COPY, function () {
GM_setClipboard(array_2_String(extract_Array(list_id)));
copy_btn.classList.add('textarea_copied');
copy_btn.title = '复制完成'
});
modifier_span.appendChild(modifier_input);
reg_span.appendChild(reg_input);
temp_div.appendChild(reg_span);
temp_div.appendChild(modifier_span);
temp_div.appendChild(add_btn);
temp_div.appendChild(delete_btn);
temp_div.appendChild(clear_btn);
temp_div.appendChild(copy_btn);
temp_li.appendChild(temp_div);
ul_node.appendChild(temp_li)
}
function insert_Textarea(ul_node, li_array, save_array) {
let temp_li = document.createElement('li');
let temp_div = document.createElement('div');
temp_div.className = 'textarea_div';
let list_div = document.createElement('div');
list_div.className = 'DmhyListDiv';
list_div.id = li_array[0];
list_div.className = 'textarea_list_div';
for (let item of save_array) {
if (item) {
list_div.insertAdjacentElement('afterbegin', create_Child(item))
}
}
temp_div.appendChild(list_div);
temp_li.appendChild(temp_div);
ul_node.appendChild(temp_li)
}
function create_Span_Btn(value_array, callback) {
let temp_span = document.createElement('span');
temp_span.className = value_array[0];
temp_span.innerText = value_array[1];
temp_span.title = value_array[2];
temp_span.addEventListener('click', function (e) {
callback(e)
}, false);
return temp_span
}
function create_Child(text_value) {
let temp_span = document.createElement('span');
temp_span.className = 'child_span';
let text_span = document.createElement('span');
text_span.className = 'DmhyTextSpan child_text';
text_span.innerText = (text_value.length > 9 ? text_value.slice(0, 3) + '...' + text_value.slice(-3) : text_value);
if (text_value.length > 9) {
text_span.title = text_value
}
let del_span = document.createElement('span');
del_span.innerText = 'X';
del_span.title = '移除';
del_span.className = 'child_del';
del_span.addEventListener('click', function () {
temp_span.parentNode.removeChild(temp_span)
});
temp_span.appendChild(text_span);
temp_span.appendChild(del_span);
return temp_span
}
function dmhy_ban_init() {
let style_dom = document.createElement('style');
style_dom.type = 'text/css';
style_dom.innerHTML = STYLE_VALUE;
let expand_box = document.createElement('div');
expand_box.className = 'expand_box';
expand_box.onmouseenter = function () {
this.classList.add('show_expand_box')
};
expand_box.onmouseleave = function () {
this.classList.remove('show_expand_box')
};
let expand_span = document.createElement('span');
expand_span.id = 'expandSpan';
expand_span.title = '打开/关闭屏蔽设置';
expand_span.innerText = '屏蔽';
expand_span.addEventListener('click', function () {
expand_Wrap('wrapDiv')
}, false);
expand_box.appendChild(expand_span);
document.body.appendChild(expand_box);
document.body.appendChild(style_dom)
let comment_block = document.querySelector('#recent-commnet');
if (comment_block)
{
comment_block.addEventListener("DOMNodeInserted", function (event) {
hide_Event();
document.querySelectorAll('span.username').forEach((item) => {
item.onclick = (e) => {
if (!document.getElementById('wrapDiv')) create_Settings();
let input = document.createElement('input');
input.value = e.target.textContent;
add_Child(input, TEXTAREA_VALUE.USERNAME[0]);
alert(`用户 ${e.target.textContent} 被添加入屏蔽列表(尚未保存)`);
};
});
}, false);
}
}
function create_Settings() {
let wrap_div = document.createElement('div');
wrap_div.id = 'wrapDiv';
wrap_div.className = 'show_wrap';
let main_tag = document.createElement('fieldset');
main_tag.id = 'mainTag';
wrap_div.appendChild(main_tag);
let ul_tag = document.createElement('ul');
ul_tag.className = 'ul_tag';
main_tag.appendChild(ul_tag);
insert_Separator(ul_tag);
insert_Separator(ul_tag, '用户名:');
insert_Input(ul_tag, INPUT_VALUE.USERNAME, TEXTAREA_VALUE.USERNAME[0]);
insert_Textarea(ul_tag, TEXTAREA_VALUE.USERNAME, dmhy_ban_config.usernameArray);
insert_Separator(ul_tag);
insert_Separator(ul_tag, '评论关键字:');
insert_Input(ul_tag, INPUT_VALUE.COMMENT_KEYWORD, TEXTAREA_VALUE.COMMENT_KEYWORD[0]);
insert_Textarea(ul_tag, TEXTAREA_VALUE.COMMENT_KEYWORD, dmhy_ban_config.commentArray);
insert_Separator(ul_tag);
insert_Separator(ul_tag, '评论正则表达式:');
insert_Reg_Input(ul_tag, INPUT_VALUE.COMMENT_REG, INPUT_VALUE.COMMENT_MODIFIER, TEXTAREA_VALUE.COMMENT_REG[0]);
insert_Textarea(ul_tag, TEXTAREA_VALUE.COMMENT_REG, dmhy_ban_config.commentRegArray);
insert_Separator(ul_tag);
let save_button = create_Span_Btn(BUTTON_VALUE.SAVE, function () {
save_Config()
});
let only_save_button = create_Span_Btn(BUTTON_VALUE.ONLY_SAVE, function () {
save_Config(false)
});
let cancel_button = create_Span_Btn(BUTTON_VALUE.CANCEL, function (e) {
expand_Wrap('wrapDiv');
e.stopPropagation()
});
ul_tag.appendChild(save_button);
ul_tag.appendChild(only_save_button);
ul_tag.appendChild(cancel_button);
document.body.appendChild(wrap_div)
}
function save_Config(close_status = true) {
dmhy_ban_config.usernameArray = extract_Array(TEXTAREA_VALUE.USERNAME[0]);
dmhy_ban_config.commentArray = extract_Array(TEXTAREA_VALUE.COMMENT_KEYWORD[0]);
dmhy_ban_config.commentRegArray = extract_Array(TEXTAREA_VALUE.COMMENT_REG[0]);
reg_config.commentRegArray = convert_Array(dmhy_ban_config.commentRegArray);
GM_setValue('dmhy_ban_config', dmhy_ban_config);
hide_Event();
if (close_status) {
expand_Wrap('wrapDiv')
}
}
function check(tr) {
let user = tr.querySelector('span.username').textContent;
let title = tr.querySelector('.title > strong').textContent;
let comment = tr.querySelector('.comment_con > span').textContent;
if (dmhy_ban_config.usernameArray.includes(user)) return true;
for (const bannedWord of dmhy_ban_config.commentArray) {
if (title.includes(bannedWord)) return true;
if (comment.includes(bannedWord)) return true;
}
for (let j of reg_config.commentRegArray) {
if (j.test(comment) || j.test(title)) {
return true
}
}
}
function hide_Event() {
for (let i of document.querySelectorAll('#comment_recent tr')) {
if (check(i)) i.hidden = true;
else i.hidden = false;
}
}
Promise.all([GM_getValue('dmhy_ban_config')]).then(function (data) {
if (data[0] !== undefined) {
dmhy_ban_config = data[0]
}
if (dmhy_ban_config.commentArray === undefined) {
dmhy_ban_config.commentArray = []
}
if (dmhy_ban_config.commentRegArray === undefined) {
dmhy_ban_config.commentRegArray = []
}
if (dmhy_ban_config.commentRegArray.length > 0) {
reg_config.commentRegArray = convert_Array(dmhy_ban_config.commentRegArray)
}
//console.log(dmhy_ban_config);
dmhy_ban_init();
hide_Event();
try {
GM_registerMenuCommand('动漫花园屏蔽设置', function () {
expand_Wrap('wrapDiv')
})
} catch (e) {
console.log(e)
}
}).
catch(function (except) {
console.log(except)
})
})();