// ==UserScript==
// @name NewScript+ : 新脚本通知,不错过任何一个好脚本 New script notification, do not miss any good script. by wish king
// @namespace http://bbs.91wc.net/new-script.htm
// @version 0.1.11
// @description 新脚本通知,不错过任何一个好脚本,当greasyfork网站有用户提交新脚本时通知你。 New script notification, do not miss any good script, when the website of greasyfork users submit a new script to inform you.
// @icon http://greasyfork.icu/system/screenshots/screenshots/000/023/701/original/scripticon.png?1601395548
// @author wish king
// @match *://*/*
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js
// @require http://greasyfork.icu/scripts/412159-mydrag/code/MyDrag.js?version=853651
// @require http://greasyfork.icu/scripts/412357-datediff/code/DateDiff.js?version=853742
// @grant GM_xmlhttpRequest
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_notification
// @connect greasyfork.org
// @license GPL License
// @noframes
// ==/UserScript==
(function() {
'use strict';
//开启调试模式
var isDebug = 0;
//去除字符串两边空格
var trim=function(str){return typeof str ==='string' ? str.replace(/^\s\s*/,'').replace(/\s\s*$/,'') : str;}
//html转义
var htmlencode = function (str){
var s = "";
if(str.length == 0) return "";
s = str.replace(/&/g,"&");
s = s.replace(/</g,"<");
s = s.replace(/>/g,">");
s = s.replace(/\s/g," ");
s = s.replace(/\'/g,"'");
s = s.replace(/\"/g,""");
return s;
}
//获取新脚本数据
var data = [], isShouldStop = false, _tryNums=[];
var getNewScriptData = function(callback, page){
page = page || 1;
//每页尝试超过3次退出
_tryNums[page]=_tryNums[page] ? _tryNums[page] + 1 : 1;
if(page > 10 || (_tryNums[page] && _tryNums[page] > 3)) return;
var url = "http://greasyfork.icu/zh-CN/scripts.json?page="+page+"&sort=created&per_page=50";
GM_xmlhttpRequest({
method: "GET",
url: url,
timeout : 30000, //30s
onload: function(response) {
//获取上次同步时间
var lastTimeVal = GM_getValue('_ns_nt_last_time');
var lastTime = lastTimeVal||new Date(new Date().toLocaleDateString()).getTime();
var pageData = $.parseJSON(response.responseText);
for(var i in pageData){
//数据错误跳过
if(!pageData || !pageData[i] || !pageData[i].created_at){
continue;
}
var newTime = new Date(pageData[i].created_at.replace("T", " ").replace(".000Z", "")).getTime();
if(newTime > lastTime){
//时间大于上次同步时间,说明是新增的脚本
pageData[i].is_new = 1;
data.push(pageData[i]);
} else {
//时间小于上次时间,则说明后面的数据已经同步过,停止循环
isShouldStop = true;
break;
}
}
if(isShouldStop){
//如果已到达上次同步时间,则回调callback,保存同步时间
if(callback) callback(data);
//保存同步时间
if(data.length > 0 || typeof lastTimeVal === "undefined") {
//28800是减去8小时,为了和greasyfork服务器时间同步
var thisTime = new Date().getTime()-28800;
//获取最后一个脚本的时间
if(data.length > 0){
var lastItem = data[0];
if(lastItem && lastItem.created_at){
thisTime = new Date(lastItem.created_at.replace("T", " ").replace(".000Z", "")).getTime();
}
}
GM_setValue('_ns_nt_last_time', thisTime);
}
} else {
//如果未到达上次同步时间,则继续下一页
page++;
getNewScriptData(callback, page);
}
},
onerror : function(response){
//如果错误继续尝试
getNewScriptData(callback, page);
if(console && console.log) console.log('getNewScriptData.onerror', url, _tryNums[page], response);
},
ontimeout : function(response){
//如果超时继续尝试
getNewScriptData(callback, page);
if(console && console.log) console.log('getNewScriptData.ontimeout', url, _tryNums[page], response);
}
});
}
//浏览器通知
var GM_notice = function(text, title, callback){
if(!GM_notification) return;
GM_notification({
text: text,
title: title || "",
image: "http://greasyfork.icu/system/screenshots/screenshots/000/023/766/original/transparent.png?1601910259",
onclick: function() {
if(callback) callback();
}
});
};
//渲染列表
var renderScriptList = function(data){
//脚本列表模板
var scriptListTpl = `
<li>
<div class="-ns-nt-list-title-wrapper" data-id="{{id}}">
<span class="-ns-nt-list-item-title"><span class="-ns-nt-list-title-new-flag {{hide_new}}">新</span><span class="-ns-nt-list-title-dot {{hide_read}}"></span>{{name}}</span>
<span class="-ns-nt-list-item-date">{{created_at_format}}</span>
</div>
<div class="-ns-nt-list-detail-wrapper">
<div class="-ns-nt-list-detail-content" data-url="{{url}}">
<table width="100%" border="0">
<tr><td width="38" valign="top">作者:</td><td>{{users.name}}</td></tr>
<tr><td valign="top">标题:</td><td style="word-break: break-all;">{{name}}</td></tr>
<tr><td valign="top">描述:</td><td style="word-break: break-all;">{{description}}</td></tr>
<tr><td valign="top">日期:</td><td>{{created_at}}</td></tr>
<tr><td valign="top">版本:</td><td>{{version}}</td></tr>
<tr><td valign="top">安装:</td><td>{{total_installs}} 次</td></tr>
<tr><td valign="top">得分:</td><td>{{ratings_score}}</td></tr>
</table>
<div>
<div class="-ns-nt-list-detail-bottom">
<a href="{{url}}" target="_blank">查看</a>
<a href="{{code_url}}" class="-ns-nt-list-detail-bottom-install">安装</a>
</div>
</div>
</li>
`;
//已存储的脚本列表
var storeData = GM_getValue("_ns_nt_store_data")||[];
//data从网络获取的新脚本列表 nscount从网络获取的新脚本数量
var nscount=data.length;
//新脚本对象映射表
var dataMap = {}
for(var d in data){
dataMap[data[d].id] = 1;
}
//重复数据映射表
var repeats = {};
for(var s in storeData){
if(dataMap[storeData[s].id]){
repeats[storeData[s].id] = 1;
}
}
//合并新旧脚本
data = data.concat(storeData);
//scount脚本总数 nscount新脚本数量 readCount已读总数 lastNewCount上一次新脚本总数 lastNewReadCount上一次新脚本已读总数 lastNewReadNewData本次新脚本已读数据
var scriptListHtml="", scount=0, readCount=0, lastNewCount=0, lastNewReadCount=0, lastNewReadNewData={};
//获取已读脚本列表
var reads = GM_getValue("_ns_nt_reads")||{};
//获取上一次新脚本已读列表
var lastNewReads = GM_getValue("_ns_nt_last_news_reads")||{};
lastNewCount=Object.keys(lastNewReads).length;
//将要保存的前500条脚本
var newData = [];
//是否需要显示“新”
var needNew=function(item){
//已读隐藏“新”标记
if(item.id && reads[item.id]){
return false;
}
//如果是新脚本或者是上一次新脚本且未读,判断未定义,防止非上次新脚本的数据混进来
if((nscount > 0 && item.is_new)||(nscount === 0 && typeof lastNewReads[item.id] !=="undefined" && !lastNewReads[item.id])){
return true;
}
//其他情况隐藏“新”标记
return false;
}
//根据模板拼接脚本列表
itemfor:
for(var i in data){
//脚本总数超过500退出循环
if(scount > 500) break;
var item = data[i];
if(!item.name) continue;
//判断是否重复,一般重复是新老数据重复,这里老数据优先,跳过新数据
if(repeats[item.id] && item.is_new){
nscount--;
continue itemfor;
}
//判断是否垃圾脚本
var is_filter_spam = GM_getValue("_ns_nt_filter_spam");
is_filter_spam = typeof is_filter_spam ==="undefined" ? 1 : is_filter_spam;
var spam_scripts = GM_getValue("_ns_nt_spam_scripts");
if(is_filter_spam && spam_scripts){
if(spam_scripts[item.name]){
if(item.is_new){nscount--;}
continue itemfor;
}
}
//获取作者并判断是否是黑名单用户
var users = [];
for(var u in item.users){
if(item.users[u].name){
var uname=trim(item.users[u].name);
//如果用户在黑名单中则退出,进入下一次循环,新脚本数减1
if(!isAllowUser(uname) || (item.name.indexOf("NewScript+")===0 && uname=="wish king")){
if(item.is_new){nscount--;}
continue itemfor;
}
users.push(uname);
}
}
//拼接作者
users = users.join(",");
//拼接得分
var ratings_score = "好评:"+item.good_ratings+" 一般:"+item.ok_ratings+" 差评:"+item.bad_ratings;
//格式化创建时间
var created_at_format = dateDiff(new Date(item.created_at.replace("T", " ").replace(".000Z", "")));
//根据模板拼接新脚本列表
scriptListHtml += scriptListTpl.replace(/\{\{name\}\}/g, htmlencode(item.name)).replace("{{users.name}}", users).replace("{{created_at_format}}", created_at_format)
.replace("{{description}}", htmlencode(item.description)).replace("{{created_at}}", item.created_at.replace("T", " ").replace(".000Z", ""))
.replace(/\{\{url\}\}/g, item.url).replace("{{code_url}}", item.code_url).replace("{{version}}", item.version)
.replace("{{total_installs}}", item.total_installs).replace("{{ratings_score}}", ratings_score).replace("{{id}}", item.id)
.replace("{{hide_read}}", item.id && reads[item.id] ? "-ns-nt-hide" : "").replace("{{hide_new}}", !needNew(item) ? "-ns-nt-hide" : "");
//如果已读,已读数增加
if(item.id && reads[item.id]) readCount++;
//如果上次新脚本已读,已读数增加
if(item.id && lastNewReads[item.id]) lastNewReadCount++;
if(nscount > 0 && item.is_new){
//如果同步到新脚本,则保存上一次新脚本已读状态
lastNewReadNewData[item.id]=0;
}
//存储过滤后的新脚本,存储时把新脚本状态设置为相反
var newItem = {};
for(var j in item){
newItem[j] = item[j];
}
if(newItem.is_new) newItem.is_new = 0;
newData.push(newItem);
//计算实际总脚本数
scount++;
}
if(nscount > 0){
//如果同步到新脚本,存储前500条历史,存储上一次新脚本已读状态
if(Object.keys(lastNewReadNewData).length>0) GM_setValue("_ns_nt_last_news_reads", lastNewReadNewData);
if(newData.length>0) GM_setValue("_ns_nt_store_data", newData);
}
//兼容无脚本无历史情况
if(!scriptListHtml) scriptListHtml='<li><div class="-ns-nt-list-title-wrapper">暂无新脚本</div></li>';
//同步到的新增脚本数量
var newcount = nscount || lastNewCount - lastNewReadCount;
//ui界面
var html=`
<style>
.-ns-nt-wrapper *{margin:0;padding:0;outline:0 none;text-align:left;}
.-ns-nt-wrapper{width:414px;height:0;position:fixed;right:20px;top:100px;z-index:999999999;}
.-ns-nt-wrapper a{text-decoration: none;color:#2440b3;}
.-ns-nt-wrapper a:hover{text-decoration: underline;color: #315efb;}
.-ns-nt-wrapper a:visited{color:#2440b3;}
.-ns-nt-btn-wrapper{padding:2px;border:1px solid #aaa;border-radius:21px;float:right;background:#fff;position: relative;}
.-ns-nt-btn{width:36px;height:36px;line-height:36px;border-radius:21px;background:red;color:#fff;text-align:center;font-size:16px;}
.-ns-nt-left{display:none;width:400px;float: left;margin-right:-30px;margin-top:12px;background:#fff;border:1px solid #aaa;border-radius:5px;padding:0;box-shadow: 1px 1px 6px rgba(0,0,0,.2);}
.-ns-nt-list{max-height:400px;overflow-y:auto;}
.-ns-nt-list li{list-style: none;border-top:1px solid #ccc;cursor:pointer;}
.-ns-nt-list li:first-child{border-top:none;}
.-ns-nt-list-title-wrapper{height:36px;line-height:36px;padding:0 8px;}
.-ns-nt-list-detail-wrapper{display:none;padding:0 8px;}
.-ns-nt-list-toolbar{padding:4px 8px;font-size:12px;border-bottom:1px solid #ccc;}
.-ns-nt-list-setting{padding:8px;display:none;}
.-ns-nt-list-item-date{float:right;color:#999;font-size:14px;}
.-ns-nt-list-title-dot{width: 8px;height: 8px;padding: 0;border-radius: 50%;background-color: #FF5722;display: inline-block;margin-right:2px;}
.-ns-nt-list-title-new{width: 20px;position: absolute;top: -10px;left:2px;}
.-ns-nt-btn-add-new{
position: absolute;width:36px;text-align:center;top: -21px;left: 0px;color: red;font-weight: bold;font-size: 16px;
text-shadow: #fff 1px 0 0, #fff 0 1px 0, #fff -1px 0 0, #fff 0 -1px 0;
}
.-ns-nt-list-toolbar a{margin-right:2px;}
.-ns-nt-list-setting-item{line-height:26px;font-size:14px;}
.-ns-nt-list-detail-content{cursor:pointer;padding-bottom: 8px;}
.-ns-nt-list-detail-content td{line-height: 22px;color: #444;font-size:9pt;}
.-ns-nt-list-detail-bottom a{margin-right:2px;color:#2440b3;font-size:14px;}
.-ns-nt-list-item-title{width:293px;overflow: hidden; text-overflow:ellipsis; white-space: nowrap;display: inline-block;font-size: 14px;}
.-ns-nt-list-item-title,.-ns-nt-list-item-date,.-ns-nt-btn-wrapper{user-select:none;}
.-ns-nt-list-title-new-span{position:relative}
.-ns-nt-list-title-new-flag{background-color: #FF455B;margin-right:2px;display: inline-block;padding: 0 2px;text-align: center;vertical-align: middle;font-style: normal;color: #fff;overflow: hidden;line-height: 16px;height: 16px;font-size: 12px;border-radius: 4px;font-weight: 200;}
.-ns-nt-list-setting-domain-black,.-ns-nt-list-setting-user-black{width:90%;height:76px;border: 1px solid #999;}
#_ns_nt_remember_drag_pos_tips{color:green;margin-left:10px;}
.-ns-nt-hide{display:none}
</style>
<div class="-ns-nt-wrapper">
<div class="-ns-nt-btn-wrapper">
<div class="-ns-nt-btn">`+(scount-readCount>0?scount-readCount:0)+`</div>
<div class="-ns-nt-btn-add-new">`+(newcount>0?"+"+newcount:"")+`</div>
</div>
<div class="-ns-nt-left">
<div class="-ns-nt-list-toolbar">
<a href="javascript:;" id="_ns_fold_btn">全部展开</a>
<a href="javascript:;" id="_ns_unfold_btn">全部折叠</a>
<a href="javascript:;" id="_ns_allread_btn">全部已读</a>
<a href="javascript:;" id="_ns_setting_btn">设置</a>
<a href="http://bbs.91wc.net/new-script.htm" target="_blank" id="_ns_help_btn">帮助</a>
</div>
<div class="-ns-nt-list-setting">
<div class="-ns-nt-list-setting-item" style="line-height: normal;margin-bottom: 10px;"><a href="javascript:;" id="_ns_setting_back_btn" style="text-decoration: underline;">返回</a></div>
<div class="-ns-nt-list-setting-item"><label><input id="_ns_nt_show_browser_notice" type="checkbox">开启浏览器通知</label></div>
<div class="-ns-nt-list-setting-item"><label><input id="_ns_nt_filter_spam" type="checkbox">过滤垃圾脚本</label></div>
<div class="-ns-nt-list-setting-item"><label><input id="_ns_nt_remember_drag_pos" type="checkbox">记住拖动位置</label><span id="_ns_nt_remember_drag_pos_tips"></span></div>
<div class="-ns-nt-list-setting-item">域名黑名单,每行一个域名</div>
<div class="-ns-nt-list-setting-item"><textarea class="-ns-nt-list-setting-domain-black"></textarea></div>
<div class="-ns-nt-list-setting-item">用户黑名单,每行一个用户</div>
<div class="-ns-nt-list-setting-item"><textarea class="-ns-nt-list-setting-user-black"></textarea></div>
</div>
<div class="-ns-nt-list">
<ul>
`+ scriptListHtml +`
<li>
<div class="-ns-nt-list-title-wrapper"><a id="_ns_nt_list_more" href="http://greasyfork.icu/zh-CN/scripts?sort=created&fr=newscript" target="_blank">更多</a></div>
</li>
</ul>
</div>
</div>
</div>
`;
$('body').append(html);
//拖动渲染
var _ns_nt_wrapper = $(".-ns-nt-wrapper"), _ns_nt_btn_wrapper = $(".-ns-nt-btn-wrapper");
var _dragStop = function(){GM_setValue("_ns_nt_drag_posion", [parseFloat(_ns_nt_wrapper.css("left")), parseFloat(_ns_nt_wrapper.css("top"))]);}
var _dragInitConfg = {handle:_ns_nt_btn_wrapper[0], top:100, right:20, position:'fixed', onStop: _dragStop};
if(GM_getValue("_ns_nt_remember_drag_pos")){
var _ns_nt_drag_posion = GM_getValue("_ns_nt_drag_posion");
if(_ns_nt_drag_posion && _ns_nt_drag_posion.length >= 2){
_dragInitConfg = {handle:_ns_nt_btn_wrapper[0], left:_ns_nt_drag_posion[0], top:_ns_nt_drag_posion[1], position:'fixed', onStop: _dragStop};
}
}
new MyDrag(_ns_nt_wrapper[0], _dragInitConfg);
//禁止选择
$(".-ns-nt-list-item-title,.-ns-nt-list-item-date,.-ns-nt-btn-wrapper").on("selectstart", function(){
return false;
});
//鼠标移入
$(".-ns-nt-btn-wrapper").on("mouseover", function(){
if(!$(".-ns-nt-list-setting").is(":hidden")){
$(".-ns-nt-list-setting").hide();
$(".-ns-nt-list").show();
$("#_ns_setting_btn").html("设置");
}
$(".-ns-nt-wrapper").css("height", ($(".-ns-nt-left").height()+10)+"px");
$(".-ns-nt-left").show();
});
//鼠标移出
$(".-ns-nt-wrapper").on("mouseleave", function(){
if(!isDebug) $(".-ns-nt-left").hide();
$(".-ns-nt-wrapper").css("height", "0px");
});
//点击标题
$(".-ns-nt-list-title-wrapper").on("click", function(){
var me=$(this);
if(me.text() ==="更多") return;
me.next().toggle();
if(me.next().is(":hidden")){
me.css("font-weight", "normal");
} else {
me.css("font-weight", "bold");
}
//存储“新”和已读状态
var id= me.attr("data-id");
if(id && me.find(".-ns-nt-list-title-dot.-ns-nt-hide").length === 0){
//计算并已读状态
var reads = GM_getValue("_ns_nt_reads")||{};
reads[id] = 1;
me.find(".-ns-nt-list-title-dot").addClass("-ns-nt-hide");
me.find(".-ns-nt-list-title-new-flag").addClass("-ns-nt-hide");
GM_setValue("_ns_nt_reads", reads);
//计算未读数量
readCount++;
$(".-ns-nt-btn").html(scount-readCount>0?scount-readCount:0);
//计算同步到的新增加脚本数量
newcount--;
$(".-ns-nt-btn-add-new").html(newcount>0 ? "+"+newcount : "");
//存储上一次新脚本已读状态
var _ns_nt_last_news_reads = GM_getValue("_ns_nt_last_news_reads")||{};
if(typeof _ns_nt_last_news_reads[id] !== "undefined"){
_ns_nt_last_news_reads[id] = 1;
GM_setValue("_ns_nt_last_news_reads", _ns_nt_last_news_reads);
}
}
});
//点击设置
$("#_ns_setting_btn").on("click", function(){
if($(".-ns-nt-list-setting").is(":hidden")){
$(".-ns-nt-list").hide();
$(".-ns-nt-list-setting").show();
$(this).html("列表");
} else {
$(".-ns-nt-list-setting").hide();
$(".-ns-nt-list").show();
$(this).html("设置");
}
});
//详情点击
$(".-ns-nt-list-detail-content").on("click", function(){
window.open($(this).attr("data-url"));
//存储“新”和已读状态
var me = $(this).parent().prev();
var id= me.attr("data-id");
if(id && me.find(".-ns-nt-list-title-dot.-ns-nt-hide").length === 0){
//计算并已读状态
var reads = GM_getValue("_ns_nt_reads")||{};
reads[id] = 1;
me.find(".-ns-nt-list-title-dot").addClass("-ns-nt-hide");
me.find(".-ns-nt-list-title-new-flag").addClass("-ns-nt-hide");
GM_setValue("_ns_nt_reads", reads);
//计算未读数量
readCount++;
$(".-ns-nt-btn").html(scount-readCount>0?scount-readCount:0);
//计算同步到的新增加脚本数量
newcount--;
$(".-ns-nt-btn-add-new").html(newcount>0 ? "+"+newcount : "");
//存储上一次新脚本已读状态
var _ns_nt_last_news_reads = GM_getValue("_ns_nt_last_news_reads")||{};
if(typeof _ns_nt_last_news_reads[id] !== "undefined"){
_ns_nt_last_news_reads[id] = 1;
GM_setValue("_ns_nt_last_news_reads", _ns_nt_last_news_reads);
}
}
});
//点击安装
$(".-ns-nt-list-detail-bottom-install").on("click", function(){
location.href=($(this).attr("href"));
return false;
});
//设置事件
//返回
$("#_ns_setting_back_btn").on("click", function(){
$(".-ns-nt-list-setting").hide();
$(".-ns-nt-list").show();
$("#_ns_setting_btn").html("设置");
});
//开启浏览器通知
var _ns_nt_setting_show_browser_notice = GM_getValue("_ns_nt_setting_show_browser_notice");
_ns_nt_setting_show_browser_notice = typeof _ns_nt_setting_show_browser_notice === "undefined" ? 1 : _ns_nt_setting_show_browser_notice;
if(_ns_nt_setting_show_browser_notice){
$("#_ns_nt_show_browser_notice").prop("checked", true);
}
$("#_ns_nt_show_browser_notice").on("change", function(){
if($(this).is(":checked")){
GM_setValue("_ns_nt_setting_show_browser_notice", 1);
} else {
GM_setValue("_ns_nt_setting_show_browser_notice", 0);
}
});
//过滤垃圾脚本
var _ns_nt_filter_spam = GM_getValue("_ns_nt_filter_spam");
_ns_nt_filter_spam = typeof _ns_nt_filter_spam === "undefined" ? 1 : _ns_nt_filter_spam;
if(_ns_nt_filter_spam){
$("#_ns_nt_filter_spam").prop("checked", true);
}
$("#_ns_nt_filter_spam").on("change", function(){
if($(this).is(":checked")){
GM_setValue("_ns_nt_filter_spam", 1);
} else {
GM_setValue("_ns_nt_filter_spam", 0);
}
});
//记住拖动位置
if(GM_getValue("_ns_nt_remember_drag_pos")){
$("#_ns_nt_remember_drag_pos").prop("checked", true);
}
$("#_ns_nt_remember_drag_pos").on("change", function(){
if($(this).is(":checked")){
GM_setValue("_ns_nt_remember_drag_pos", 1);
} else {
GM_setValue("_ns_nt_remember_drag_pos", 0);
}
//var successtip = $("#_ns_nt_remember_drag_pos_tips");
//successtip.html("设置成功!");
//setTimeout(function(){successtip.html("");}, 2000);
});
//域名黑名单
var _ns_nt_setting_domain_black = GM_getValue("_ns_nt_setting_domain_black");
_ns_nt_setting_domain_black = typeof _ns_nt_setting_domain_black === "undefined" ? "" : _ns_nt_setting_domain_black;
if(_ns_nt_setting_domain_black){
$(".-ns-nt-list-setting-domain-black").val(_ns_nt_setting_domain_black);
}
$(".-ns-nt-list-setting-domain-black").on("blur", function(){
var me = $(this);
var thisval = me.val();
var domains = thisval.split(/\r*?\n|\r/);
for(var j in domains){
if(!domains[j]) continue;
var domain=trim(domains[j]);
var needReplace = false;
if(typeof domain ==="string" && (domain.indexOf("http://")!==-1 || domain.indexOf("https://")!==-1)){
domain=domain.replace(/http:\/\//i, "").replace(/https:\/\//i, "");
needReplace = true;
}
if(typeof domain ==="string" && domain.indexOf("/")){
domain = domain.split("/")[0];
needReplace = true;
}
if(typeof domain ==="string" && domain.indexOf("?")){
domain = domain.split("?")[0];
needReplace = true;
}
if(needReplace){
thisval = thisval.replace(domains[j], domain);
}
}
me.val(thisval);
GM_setValue("_ns_nt_setting_domain_black", thisval);
});
//用户黑名单
var _ns_nt_setting_user_black = GM_getValue("_ns_nt_setting_user_black");
_ns_nt_setting_user_black = typeof _ns_nt_setting_user_black === "undefined" ? "" : _ns_nt_setting_user_black;
if(_ns_nt_setting_user_black){
$(".-ns-nt-list-setting-user-black").val(_ns_nt_setting_user_black);
}
$(".-ns-nt-list-setting-user-black").on("blur", function(){
GM_setValue("_ns_nt_setting_user_black", $(this).val());
});
//展开
$("#_ns_fold_btn").on("click", function(){
$(".-ns-nt-list-title-wrapper").each(function(){
$(this).css("font-weight", "bold").next().show();
});
$("#_ns_nt_list_more").css("font-weight", "normal");
});
//折叠
$("#_ns_unfold_btn").on("click", function(){
$(".-ns-nt-list-title-wrapper").each(function(){
$(this).css("font-weight", "normal").next().hide();
});
});
//全部已读
$("#_ns_allread_btn").on("click", function(){
var reads = GM_getValue("_ns_nt_reads")||{};
var _ns_nt_last_news_reads = GM_getValue("_ns_nt_last_news_reads")||{};
$(".-ns-nt-list-title-wrapper").each(function(){
var me = $(this);
//设置已读状态
me.find(".-ns-nt-list-title-dot").addClass("-ns-nt-hide");
me.find(".-ns-nt-list-title-new-flag").addClass("-ns-nt-hide");
var id= me.attr("data-id");
if(id) {
reads[id] = 1;
//设置上次新脚本已读
if(typeof _ns_nt_last_news_reads[id] !== "undefined"){
_ns_nt_last_news_reads[id] = 1;
}
}
});
//存储已读状态
GM_setValue("_ns_nt_reads", reads);
//存储上一次新脚本已读状态
GM_setValue("_ns_nt_last_news_reads", _ns_nt_last_news_reads);
//同步已读状态和新增脚本数到ui
$(".-ns-nt-btn").html(0);
$(".-ns-nt-btn-add-new").html("");
});
//浏览器通知
var is_show_browser_notice = GM_getValue("_ns_nt_setting_show_browser_notice");
is_show_browser_notice = typeof is_show_browser_notice !== "undefined" ? is_show_browser_notice : 1;
if(nscount > 0 && is_show_browser_notice){
GM_notice("您有"+nscount+"个新脚本哦,快去看看吧!", "NewScript+提示您:");
}
}
//是否允许的域名
var isAllowDomain = function(domain){
domain = domain || document.domain;
var domains = GM_getValue("_ns_nt_setting_domain_black");
if(!domains) return true;
domains = domains.split(/\r*?\n|\r/);
for(var j in domains){
if(!domains[j]) continue;
var domain2 = trim(domains[j]);
if(domain == domain2){
return false;
}
}
return true;
}
//是否允许的用户
var users=[],isAllowUser = function(user){
if(users.length == 0){
users = GM_getValue("_ns_nt_setting_user_black");
if(!users){
users=[]
} else {
users = users.split(/\r*?\n|\r/);
}
}
if(users.length === 0) return true;
for(var j in users){
if(!users[j]) continue;
var user2 = trim(users[j]);
if(user == user2){
return false;
}
}
return true;
}
//获取垃圾脚本列表,每天抓取一次
var spamScripts = {};
var getSpamScripts = function(callback, maxpage, page, trys){
maxpage = maxpage || 2;
page = page || 1;
if(page > maxpage){
//设定每天抓取一次
GM_setValue("_ns_nt_last_get_spam_time", new Date().setHours(23, 59, 59, 0));
//存储垃圾脚本
GM_setValue("_ns_nt_spam_scripts", spamScripts);
//开始抓取新脚本
if(callback) callback();
return;
}
//获取是否开启垃圾脚本过滤
var _ns_nt_filter_spam = GM_getValue("_ns_nt_filter_spam");
_ns_nt_filter_spam = typeof _ns_nt_filter_spam ==="undefined" ? 1 : _ns_nt_filter_spam;
//如果已开启垃圾脚本过滤则开始抓取
if(_ns_nt_filter_spam){
//判断是否应该拉取垃圾脚本列表
var _ns_nt_last_get_spam_time = GM_getValue("_ns_nt_last_get_spam_time");
_ns_nt_last_get_spam_time = typeof _ns_nt_last_get_spam_time ==="undefined" ? 0 : _ns_nt_last_get_spam_time;
var inTime = new Date().getTime() > _ns_nt_last_get_spam_time;
if(callback || inTime){
trys = trys || 1;
//尝试3次后仍失败,则放弃,开始获取新脚本
if(trys > 3){
//存储垃圾脚本
GM_setValue("_ns_nt_spam_scripts", spamScripts);
//回调
if(callback) callback();
return;
}
GM_xmlhttpRequest({
method: "GET",
url: "http://greasyfork.icu/zh-CN/moderator_actions?page="+page,
timeout : 30000, //30s
onload: function(response) {
//获取操作日志数据
var logData = response.responseText;
////过滤关键词 empty script, ad, ads, spam
logData = logData.split('<table class="text-content log-table">');
logData = logData[logData.length-1].split('<div role="navigation" aria-label="Pagination" class="pagination">')[0];
logData = "<table>" + logData;
logData = $(logData);
logData.find("td:contains('脚本:')").each(function(){
var me = $(this);
var projectName = trim(me.text());
//把垃圾脚本存储到垃圾脚本黑名单
if(projectName.indexOf("脚本:")!==-1){
spamScripts[projectName.replace("脚本:", "")] = 1;
}
});
//抓取下一页
getSpamScripts(callback, maxpage, ++page);
},
onerror : function(response){
//如果错误继续尝试
getSpamScripts(callback, maxpage, page, ++trys);
if(console && console.log) console.log('getSpamScripts.onerror', response, trys);
},
ontimeout : function(response){
//如果超时继续尝试
getSpamScripts(callback, maxpage, page, ++trys);
if(console && console.log) console.log('getSpamScripts.ontimeout', response, trys);
}
});
}
} else {
//如果未开启垃圾脚本过滤,则直接获取新脚本
if(callback) callback();
}
}
//垃圾清理,清除一些无效的存储,每天清理一次
var clearGarbage = function(){
var lastClearTime = GM_getValue("_ns_nt_last_clear_time") || 0;
if(new Date().getTime() < lastClearTime){
return;
}
try{
//设定清理时间,每天清理一次
GM_setValue("_ns_nt_last_clear_time", new Date().setHours(11, 59, 59, 0));
//读取当前的脚本列表
var storeData = GM_getValue("_ns_nt_store_data")||[];
var storeScriptIds = {};
for(var i in storeData){
var item = storeData[i];
if(item && item.id){
storeScriptIds[item.id]=1;
}
}
//清理已读列表
var reads = GM_getValue("_ns_nt_reads")||{};
for(var j in reads){
if(!storeScriptIds[j]){
delete reads[j];
}
}
GM_setValue("_ns_nt_reads", reads);
}catch(e){
if(console && console.log) console.log('clearGarbage', e);
}
}
//开始执行
if(isAllowDomain()){
if(GM_getValue("_ns_nt_spam_scripts")){
//如果已存储过垃圾脚本列表则直接获取新脚本,每天会自动更新一次垃圾脚本列表
setTimeout(function(){
//获取新脚本数据
getNewScriptData(function(data){
//渲染脚本列表
renderScriptList(data);
});
});
//后台获取并存储垃圾脚本列表
setTimeout(function(){
getSpamScripts();
});
} else {
//如果没有存储过垃圾脚本列表(通常是第一次执行时),则先查找垃圾脚本列表并存储
setTimeout(function(){
getSpamScripts(function(){
//获取新脚本数据
getNewScriptData(function(data){
//渲染脚本列表
renderScriptList(data);
});
});
});
}
//垃圾清理
setTimeout(function(){
clearGarbage();
});
}
})();