// ==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 */ '
' + ' ' + ' ' + ' ' + ' ' + '
' + '
    ' + '
  • ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + '
    ' + '
    ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' B' + ' I' + ' U' + '
    ' + '
     ' + '

    ' + ' ' + ' ' + ' ^' + '

    ' + '
    ' + '
  • ' + '
' + '
' + '
' + /* 提交按钮 */ '

' + ' ' + ' ' + '

' + '
' + '
' + '
' ).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));