// ==UserScript==
// @name 天使动漫一键评分
// @namespace https://greasyfork.org/users/4514
// @author 喵拉布丁
// @homepage https://github.com/miaolapd/TsdmOneKeyRating
// @description 在天使动漫论坛版块页面里,为所选的帖子进行一键评分(可自行修改默认评分设置)
// @include http://www.tsdm.net/forum.php?mod=forumdisplay*
// @include http://www.tsdm.me/forum.php?mod=forumdisplay*
// @require https://code.jquery.com/jquery-3.1.1.min.js
// @version 1.3
// @grant none
// @run-at document-end
// @license MIT
// @include-jquery true
// @downloadURL https://update.greasyfork.icu/scripts/20839/%E5%A4%A9%E4%BD%BF%E5%8A%A8%E6%BC%AB%E4%B8%80%E9%94%AE%E8%AF%84%E5%88%86.user.js
// @updateURL https://update.greasyfork.icu/scripts/20839/%E5%A4%A9%E4%BD%BF%E5%8A%A8%E6%BC%AB%E4%B8%80%E9%94%AE%E8%AF%84%E5%88%86.meta.js
// ==/UserScript==
/**
* 配置项
*/
var Config = {
// 是否在选择的时候排除已评分的帖子,true:开启;false:关闭
excludeRatingThreadEnabled: true,
// 是否在选择的时候排除自己的帖子,true:开启;false:关闭
excludeMyThreadEnabled: true,
// 是否在关闭评分结果对话框后自动刷新页面,true:开启;false:关闭
refreshPageAfterCloseRatingResultDialogEnabled: true,
// ajax请求的时间间隔(毫秒)
ajaxInterval: 200,
// ajax请求的超时时间(毫秒)
ajaxTimeout: 20000
};
/**
* 默认评分设置
* 关键字:可通过jQuery选择的dom对象
* 值:想要设置的预设值
* @example
* var DefValueConfig = {
* '[name="score1"]': '+1', // 将威望设为+1
* '[name="score2"]': '+2', // 将天使币设为+1
* '[name="score3"]': '+3', // 将宣传设为+1
* '[name="score4"]': '+4', // 将天然设为+1
* '[name="score5"]': '+5', // 将腹黑设为+1
* '[name="score6"]': '-1', // 将精灵设为-1
* '#reason': '很给力', // 将评分理由设为“很给力”
* '#highlight_thread': true, // 高亮帖子
* '[name="highlight_color"]': '4', // 将帖子高亮颜色设为深绿色
* '#highlight_op_1': true, // 将帖子标题设为粗体
* '#highlight_op_2': true, // 将帖子标题设为斜体
* '#highlight_op_3': true, // 为帖子标题添加下划线
* '[name="sendreasonpm"]': true, // 勾选通知作者的复选框
* };
*/
var DefValueConfig = {
'[name="score1"]': '+10',
'[name="score2"]': '+20',
'#highlight_thread': true,
'[name="highlight_color"]': '4',
'#highlight_op_1': true,
};
jQuery.noConflict();
(function ($) {
// 用户的formHash
var formHash = '';
// 自己的用户名
var userName = '';
// window对象
var w = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window;
// 高亮颜色可选项
var highlightColorOptions = {
'0': '#000',
'1': '#EE1B2E',
'2': '#EE5023',
'3': '#996600',
'4': '#3C9D40',
'5': '#2897C5',
'6': '#2B65B7',
'7': '#8F2A90',
'8': '#EC1282'
};
/**
* 添加CSS
*/
var appendCss = function () {
$('head').append(
''
);
};
/**
* 显示提示消息
* @param {string} msg 提示消息
* @param {boolean} [canClose=false] 是否可以关闭
* @returns {jQuery} 消息框的jQuery对象
*/
var showMsg = function (msg, canClose) {
if (!$('.pd_mask').length) $('
').appendTo('body');
var $msg = $(
'' +
'
' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' {0} '.replace('{0}', msg) +
' 关闭 ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
'
' +
'
'
).appendTo('#append_parent');
if (canClose) {
$msg.find('.pd_msg_close').click(function () {
$(this).closest('#fwin_dialog').data('stop', true);
}).parent().css('display', 'inline');
}
$msg.css('top', $(window).height() / 2 - $msg.height() / 2)
.css('left', $(window).width() / 2 - $msg.width() / 2);
return $msg;
};
/**
* 隐藏提示消息
* @param {jQuery} $msg 消息框的jQuery对象
*/
var hideMsg = function ($msg) {
$msg.remove();
$('.pd_mask').remove();
};
/**
* 输出经过格式化后的控制台消息
* @param {string} type 消息类别
* @param {string} msg 回应消息
*/
var showFormatLog = function (type, msg) {
var result = '';
if (/succeedhandle_/i.test(msg)) {
var matches = /succeedhandle_\w+\('[^']*',\s*'([^']*)'/i.exec(msg);
if (matches) result = $.trim(matches[1]);
}
else if (/errorhandle_/i.test(msg)) {
var matches = /errorhandle_\w+\('([^']*)'/i.exec(msg);
if (matches) result = $.trim(matches[1]);
}
if (!result) result = '未能获得预期的回应';
console.log('【{0}】回应:{1}'.replace('{0}', type).replace('{1}', result));
};
/**
* 获取经过本地编码后的字符串
* @param {string} str 待编码的字符串
* @returns {string} 经过本地编码后的字符串
*/
var getLocaleEncodeString = function (str) {
var img = $(' ').appendTo('body').get(0);
img.src = 'nothing?sp=' + str;
var encodeStr = img.src.split('nothing?sp=').pop();
$(img).remove();
return encodeStr;
};
/**
* 排除置顶的帖子
*/
var excludeTopThread = function () {
$('input[name="moderate[]"]:checked').each(function () {
var $this = $(this);
if ($this.parent('td').prev('td').find('a[title*="置顶"]').length > 0) {
$this.prop('checked', false);
}
});
};
/**
* 排除已评分的帖子
*/
var excludeRatingThread = function () {
$('input[name="moderate[]"]:checked').each(function () {
var $this = $(this);
if ($this.parent('td').next().find('img[title="帖子被加分"]').length > 0) {
$this.prop('checked', false);
}
});
};
/**
* 排除自己的帖子
*/
var excludeMyThread = function () {
$('input[name="moderate[]"]:checked').each(function () {
var $this = $(this);
if ($this.parent('td').next().next('td').find('cite > a').text() === userName) {
$this.prop('checked', false);
}
});
};
/**
* 添加一键评分相关按钮
*/
var addRatingBtns = function () {
$(
'' +
' 全选 ' +
' 反选 ' +
' 一键评分 ' +
' 排除已评分的帖子 '
.replace('{0}', Config.excludeRatingThreadEnabled ? ' checked="checked"' : '') +
' 排除自己的帖子 '
.replace('{0}', Config.excludeMyThreadEnabled ? ' checked="checked"' : '') +
'
'
).insertBefore('#diyfastposttop').on('click', 'button', function (e) {
e.preventDefault();
var action = $(this).data('action');
if (action === 'selectAll') {
$('input[name="moderate[]"]').prop('checked', true);
excludeTopThread();
if ($('#pd_exclude_rating').prop('checked')) excludeRatingThread();
if ($('#pd_exclude_my_thread').prop('checked')) excludeMyThread();
}
else if (action === 'selectInverse') {
$('input[name="moderate[]"]').each(function () {
$(this).prop('checked', !$(this).prop('checked'));
});
excludeTopThread();
if ($('#pd_exclude_rating').prop('checked')) excludeRatingThread();
if ($('#pd_exclude_my_thread').prop('checked')) excludeMyThread();
}
else if (action === 'oneKeyRating') {
if (!$('input[name="moderate[]"]:checked').length) {
alert('请选择要评分的帖子');
return;
}
showRatingDialog();
}
});
$(document).on('click', 'input[name="moderate[]"]', function () {
if ($('.pd_select_thread_num').length > 0) {
$('.pd_select_thread_num').text($('input[name="moderate[]"]:checked').length);
}
});
};
/**
* 显示一键评分对话框
*/
var showRatingDialog = function () {
if ($('#fwin_rate').length > 0) return;
$('#mdly').remove();
w.pd_modeRateData = null;
var $dialog = $(
'' +
'
' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
'
' +
' 一键评分 (共选择了0 个帖子) 关闭 ' +
' ' +
/* 评分form */
'
' +
/* 高亮form */
'
' +
/* 提交按钮 */
'
' +
' 通知作者 ' +
' 确定 ' +
'
' +
'
' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
'
' +
'
'
).appendTo('#append_parent');
$dialog.end().find('.pd_select_thread_num').text($('input[name="moderate[]"]:checked').length)
.end().find('input[name="formhash"]').val(formHash)
.end().find('input[name="fid"]').val($('input[name="srhfid"]').val())
.end().find('input[name="referer"]').val(location.href)
.end().find('input[name="redirect"]').val(location.href);
$dialog.find('#reasonselect').on('mouseover', 'li', function () {
$(this).addClass('xi2 cur1');
}).on('mouseout', 'li', function () {
$(this).removeClass('xi2 cur1');
}).on('click', 'li', function () {
$('#reason').val($(this).text());
}).end().find('#reason').keyup(function (e) {
if (e.keyCode === 13) $dialog.find('#ratesubmit').click();
});
$dialog.on('click', '[id^="highlight_op_"]', function () {
var $this = $(this);
var id = $this.data('id');
if (parseInt($('#highlight_style_' + id).val())) {
$('#highlight_style_' + id).val(0);
$this.removeClass('cnt');
}
else {
$('#highlight_style_' + id).val(1);
$this.addClass('cnt');
}
});
w.showHighLightColor = function (hlid) {
var showid = hlid + '_ctrl';
if (!document.getElementById(showid + '_menu')) {
var str = '';
var coloroptions = highlightColorOptions;
var menu = document.createElement('div');
menu.id = showid + '_menu';
menu.className = 'cmen';
menu.style.display = 'none';
for (var i in coloroptions) {
str += '' + coloroptions[i] + ' ';
}
menu.innerHTML = str;
document.getElementById('append_parent').appendChild(menu);
}
showMenu({'ctrlid': hlid + '_ctrl', 'evt': 'click', 'showid': showid});
};
w.today = new Date();
$dialog.find('form').submit(function (e) {
e.preventDefault();
$dialog.find('#ratesubmit').click();
}).end().find('#ratesubmit').click(function (e) {
e.preventDefault();
if (!$('input[name="moderate[]"]:checked').length) {
alert('请选择要评分的帖子');
return;
}
batchRating($dialog);
});
$.each(DefValueConfig, function (key, value) {
if (key.indexOf('highlight_color') > -1) {
$dialog.find(key).val(value)
.end().find('#highlight_color_ctrl').css('background-color', highlightColorOptions[value]);
}
else if (typeof value === 'boolean') {
if (value) $dialog.find(key).click();
}
else {
$dialog.find(key).val(value);
}
});
$dialog.css('top', $(window).height() / 2 - $dialog.height() / 2)
.css('left', $(window).width() / 2 - $dialog.width() / 2);
};
/**
* 批量评分
* @param {jQuery} $dialog 评分对话框的jQuery对象
*/
var batchRating = function ($dialog) {
var tidList = [], pidList = {};
$('input[name="moderate[]"]:checked').each(function () {
tidList.push($(this).val());
});
var rateData = $dialog.find('#rateform').serialize();
var modeRateData = $dialog.find('#moderateform').serialize();
var reason = $.trim($dialog.find('#reason').val());
if (reason) {
rateData += '&reason=' + getLocaleEncodeString(reason);
}
if ($dialog.find('#sendreasonpm').prop('checked')) {
rateData += '&sendreasonpm=on';
}
modeRateData += '&moderate%5B%5D={0}'.replace('{0}', tidList[0]);
if ($dialog.find('input[name="operations[]"][value="highlight"]').prop('checked')) {
w.pd_modeRateData = modeRateData;
}
$dialog.remove();
var $msg = showMsg('正在获取各帖子的pid,请稍后...剩余数量:{0} '.replace('{0}', tidList.length), true);
var count = 0;
var itvFuncList = [];
$.each(tidList, function (index, tid) {
var itvFunc = window.setTimeout(function () {
$.ajax({
type: 'GET',
url: 'forum.php?mod=viewthread&tid=' + tid,
timeout: Config.ajaxTimeout,
success: function (html) {
var matches = /= tidList.length) {
hideMsg($msg);
rating(tidList, pidList, rateData);
}
}
});
}, index * Config.ajaxInterval);
itvFuncList.push(itvFunc);
});
};
/**
* 评分
* @param {number[]} tidList 帖子ID列表
* @param {{}} pidList 帖子顶楼的pid列表
* @param {string} rateData 提交评分的数据
*/
var rating = function (tidList, pidList, rateData) {
var $msg = showMsg('正在进行评分,请稍后...剩余数量:{0} '.replace('{0}', tidList.length));
var successNum = 0, failNum = 0;
var failList = [];
$.each(tidList, function (index, tid) {
window.setTimeout(function () {
var pid = pidList[tid] ? pidList[tid] : 0;
$.ajax({
type: 'POST',
url: 'forum.php?mod=misc&action=rate&ratesubmit=yes&infloat=yes&inajax=1',
data: rateData + '&tid={0}&pid={1}'.replace('{0}', tid).replace('{1}', pid),
timeout: Config.ajaxTimeout,
success: function (xml) {
var msg = xml.documentElement ? xml.documentElement.textContent : '';
showFormatLog('评分', msg);
if (/succeedhandle_rate\(/i.test(msg)) {
successNum++;
}
else if (/errorhandle_rate\(/i.test(msg)) {
failNum++;
var matches = /errorhandle_rate\('([^']*)'/i.exec(msg);
failList.push({tid: tid, pid: pid, failMsg: matches ? matches[1] : '未知的回应'});
}
else {
failNum++;
failList.push({tid: tid, pid: pid, failMsg: '未知的回应'});
}
},
error: function () {
failNum++;
failList.push({tid: tid, pid: pid, failMsg: '连接超时'});
},
complete: function () {
$('#pd_count').text(tidList.length - successNum - failNum);
if (successNum + failNum >= tidList.length) {
hideMsg($msg);
showRatingResultDialog(successNum, failNum, failList);
if (w.pd_modeRateData) highlightThread(tidList, w.pd_modeRateData);
}
}
});
}, index * Config.ajaxInterval);
});
};
/**
* 显示一键评分结果的对话框
* @param {number} successNum 评分成功数量
* @param {number} failNum 评分失败数量
* @param {[]} failList 评分失败列表
*/
var showRatingResultDialog = function (successNum, failNum, failList) {
var $dialog = $(
'' +
'
' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
'
' +
(' 评分结果 (共有{1} 个帖子评分成功,' +
'共有{2} 个帖子评分失败 ) ')
.replace('{0}', w.pd_modeRateData ? 'min-width:540px' : '')
.replace('{1}', successNum)
.replace('{2}', failNum) +
' 关闭 ' +
' ' +
'
' +
'
' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
'
' +
'
'
).appendTo('#append_parent');
var result = '';
$.each(failList, function (index, obj) {
var $node = $('input[name="moderate[]"][value="{0}"]'.replace('{0}', obj.tid));
if (!$node.length) return;
var $link = $node.parent('td').next().find('span > a.xst');
if (!$link.length) return;
result += '{1} 失败原因: {3} '
.replace('{0}', $link.attr('href'))
.replace(/\{1\}/g, $link.text())
.replace('{2}', $node.parent('td').next().next('td').find('cite > a').text())
.replace(/\{3\}/g, obj.failMsg);
});
if (result) {
$dialog.find('#pd_rating_result').html('评分失败项目: ' + result + ' ').css('display', 'block');
}
$dialog.find('.flbc').click(function () {
$dialog.remove();
if (Config.refreshPageAfterCloseRatingResultDialogEnabled) location.reload();
});
$dialog.css('top', $(window).height() / 2 - $dialog.height() / 2)
.css('left', $(window).width() / 2 - $dialog.width() / 2);
};
/**
* 高亮帖子
* @param {number[]} tidList 帖子ID列表
* @param {string} modeRateData 提交高亮帖子的数据
*/
var highlightThread = function (tidList, modeRateData) {
var $msg = showMsg('正在高亮帖子,请稍后...');
$.each(tidList, function (i, tid) {
modeRateData += '&moderate%5B%5D=' + tid;
});
var isSuccess = false;
var failReason = '';
$.ajax({
type: 'POST',
url: 'forum.php?mod=topicadmin&action=moderate&optgroup=1&modsubmit=yes&infloat=yes&inajax=1',
data: modeRateData,
timeout: Config.ajaxTimeout,
success: function (xml) {
var msg = xml.documentElement ? xml.documentElement.textContent : '';
showFormatLog('高亮帖子', msg);
if (/succeedhandle_mods\(/i.test(msg)) {
isSuccess = true;
}
else if (/errorhandle_mods\(/i.test(msg)) {
var matches = /errorhandle_mods\('([^']*)'/i.exec(msg);
failReason = matches ? matches[1] : '未知的回应';
}
else {
failReason = '未知的回应';
}
},
error: function () {
failReason = '连接超时';
},
complete: function () {
hideMsg($msg);
if (isSuccess) {
$('#pd_highlight_thread_result').html(',共有{0} 个帖子高亮成功'.replace('{0}', tidList.length));
}
else {
$('#pd_highlight_thread_result')
.html(',共有{0} 个帖子高亮失败'.replace('{0}', tidList.length))
.attr('title', '原因:' + failReason)
.css('cursor', 'help');
}
}
});
w.pd_modeRateData = null;
};
/**
* 初始化
*/
var init = function () {
if (!$('input[name="moderate[]"]').length) return;
var hashMatches = /formhash=(\w+)/i.exec($('#toptb a[href*="formhash="]').attr('href'));
if (hashMatches) formHash = hashMatches[1];
else return;
userName = $('#toptb a[href*="home.php?mod=space&uid="]').text();
if (!userName) return;
appendCss();
addRatingBtns();
console.log('【天使动漫一键评分】加载完毕');
};
init();
}(jQuery));