// ==UserScript== // @namespace http://bbs.91wc.net/new-script.htm // @version 0.1.45 // @author wish king // @name NewScript+ : 新脚本通知,不错过任何一个好脚本 // @name:en NewScript+ : New script notification, do not miss any good script // @name:zh NewScript+ : 新脚本通知,不错过任何一个好脚本 // @name:zh-CN NewScript+ : 新脚本通知,不错过任何一个好脚本 // @name:zh-TW NewScript+ : 新腳本通知,不錯過任何一個好腳本 // @name:ja NewScript+ : 新しいスクリプトのお知らせは、良いスクリプトを見逃さないようにします // @name:ko NewScript+ : 새 스 크 립 트 알림, 좋 은 스 크 립 트 를 놓 치지 않 습 니 다 // @description 新脚本通知,不错过任何一个好脚本,当greasyfork网站有用户提交新脚本时通知你。 // @description:en New script notification, do not miss any good script, when the website of greasyfork users submit a new script to inform you. // @description:zh 新脚本通知,不错过任何一个好脚本,当greasyfork网站有用户提交新脚本时通知你。 // @description:zh-CN 新脚本通知,不错过任何一个好脚本,当greasyfork网站有用户提交新脚本时通知你。 // @description:zh-TW 新腳本通知,不錯過任何一個好腳本,當greasyfork網站有用戶提交新腳本時通知你。 // @description:ja 新しいスクリプトのお知らせは、良いスクリプトを見逃さずに、greasyforkウェブサイトのユーザーが新しいスクリプトを提出した時にお知らせします。 // @description:ko 새 스 크 립 트 알림, 좋 은 스 크 립 트 를 놓 치지 않 습 니 다. greasyfork 사이트 에서 사용자 가 새 스 크 립 트 를 제출 할 때 알려 드 립 니 다. // @icon https://greasyfork.org/system/screenshots/screenshots/000/023/701/original/scripticon.png?1601395548 // @match *://*/* // @require https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js // @require https://greasyfork.org/scripts/412159-mydrag/code/MyDrag.js?version=853651 // @require https://greasyfork.org/scripts/412357-datediff/code/DateDiff.js?version=853742 // @resource r2_favorite_icon https://greasyfork.org/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBcnBXIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--96e6f39247ac3675b622982c3716b47ec80bdce6/favorite.png?locale=zh-CN // @resource r1_notice_icon https://greasyfork.org/system/screenshots/screenshots/000/023/766/original/transparent.png?1601910259 // @resource r1_silent_mode_tips https://greasyfork.org/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBcWxXIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--5983520c5085da9140f885278762eff9ad78aef6/exit_silent_mode.png?locale=zh-CN // @grant GM_getResourceURL // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_notification // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_setClipboard // @connect greasyfork.org // @license GPL License // @noframes // @downloadURL https://update.greasyfork.icu/scripts/412611/NewScript%2B%20%3A%20%E6%96%B0%E8%84%9A%E6%9C%AC%E9%80%9A%E7%9F%A5%EF%BC%8C%E4%B8%8D%E9%94%99%E8%BF%87%E4%BB%BB%E4%BD%95%E4%B8%80%E4%B8%AA%E5%A5%BD%E8%84%9A%E6%9C%AC.user.js // @updateURL https://update.greasyfork.icu/scripts/412611/NewScript%2B%20%3A%20%E6%96%B0%E8%84%9A%E6%9C%AC%E9%80%9A%E7%9F%A5%EF%BC%8C%E4%B8%8D%E9%94%99%E8%BF%87%E4%BB%BB%E4%BD%95%E4%B8%80%E4%B8%AA%E5%A5%BD%E8%84%9A%E6%9C%AC.meta.js // ==/UserScript== (function() { 'use strict'; //开启调试模式 var isDebug = 0; //语言映射 var langMap = { "全部展开" : "Expand all", "全部折叠" : "Fold all", "全部已读" : "Read all", "我的收藏" : "My Favorites", "免打扰模式" : "Do Not Disturb Mode", "退出免打扰模式" : "Exit Do Not Disturb Mode", "设置" : "Settings", "帮助" : "Help", "更多" : "More", "作者:" : "Author: ", "标题:" : "Title: ", "描述:" : "Description: ", "创建:" : "Created: ", "版本:" : "Version: ", "安装:" : "Install: ", "得分:" : "Score: ", "好评:" : "Good: ", "一般:" : "General: ", "差评:" : "Bad: ", "查看" : "View", "源码" : "Source", "安装" : "Install", "收藏" : "Favorite", "取消收藏" : "Unfavorite", "次" : "times", "刚刚" : "Just now", "分钟前" : "minutes ago", "个小时前" : "hours ago", "天前" : "days before", "周前" : "weeks before", "个月前" : "months ago", "年前" : "years ago", "返回" : "Go back", "开启浏览器通知" : "Open browser notification", "开启收藏功能" : "Enable Favorites", "过滤垃圾脚本" : "Filter junk scripts", "记住拖动位置" : "Remember the drag position", "检查频率" : "Remember the drag position", "总是" : "Always", "每" : "Every", "分钟" : "minutes", "监听哪个语言的新脚本?" : "Which language to listen for new scripts?", "中文" : "Chinese", "英文" : "English", "所有语言" : "All languages", "界面显示语言" : "Interface display language", "域名黑名单,每行一个域名" : "Domain blacklist, one domain name per line", "用户黑名单,每行一个用户" : "User blacklist, one user per line", "标题关键词黑名单,每行一个关键词" : "Title keyword blacklist, one keyword per line", "清除缓存" : "Clear cache", "暂无新脚本" : "No new script yet", "暂无收藏" : "No Favorites", "收藏失败" : "Favorite failed", "已收藏" : "Favorited", "已取消" : "Canceled", "设置成功,刷新页面后生效" : "Set successfully, take effect after refreshing the page", "设置成功,已进入免打扰模式" : "Set up successfully, has entered Do Not Disturb mode", "免打扰模式下,不显示提示图标,仅在有新脚本时才显示,也可在菜单中退出免打扰模式,见下图:" : "In the Do Not Disturb mode, the prompt icon is not displayed, and it is only displayed when there is a new script. You can also exit the Do Not Disturb mode in the menu, see the figure below: ", "不再提示" : "Do not remind again", "关 闭" : "shut down", "当出现莫名其妙的错误时,可以尝试清除缓存;\u000d清除缓存将清除历史脚本记录,但设置和收藏的脚本不会清除;\u000d点击[确定],将会清除缓存并重新加载页面\u000d点击[取消],将取消本次操作\u000d你确定要继续清除吗?此操作不可恢复!" : "When an inexplicable error occurs, you can try to clear the cache; \u000dClearing the cache will clear the history script records, but the scripts of settings and favorites will not be cleared; \u000d Click [OK], the cache will be cleared and the page will be reloaded\u000d Click [Cancel] to cancel this operation\u000dAre you sure you want to continue cleaning? This operation cannot recovery!", "您有" : "You have", "个新脚本哦,快去看看吧!" : "new scripts, go and take a look!", "NewScript+提示您:" : "NewScript+ prompts you:", "新" : "New", "设置成功" : "Set successfully", "垃圾脚本" : "Junk script", "脚本:" : "Script:", "查看代码" : "View code", "复制代码" : "Copy code", "已复制到剪贴板" : "Copied to clipboard", "代码" : "Code", "信息" : "Info", "历史版本" : "History", "反馈" : "Feedback", "统计数据" : "Stats" }; //界面支持的语言,默认是浏览器语言 var defLang = navigator.language||navigator.userLanguage||"zh-CN"; defLang = defLang == "zh-CN" ? defLang : "en"; //界面显示的语言 var langui = GM_getValue("_ns_nt_langui", defLang)||defLang; //界面是否是中文 var isCNUi = langui == "zh-CN"; //监听哪个语言的脚本,默认是浏览器语言 var langVal = GM_getValue("_ns_nt_lang", defLang)||defLang; //监听哪个语言的新脚本,all的时候去界面的语言,这个langType会在跳转链接里显示,all时真正起作用的是filterLocale标志 var langType = langVal == "all" ? langui : langVal; //监听所有语言的新脚本标志 var filterLocale = langVal == "all" ? "&filter_locale=0" : ""; //是否监听中文的新脚本 var isCNType = langType == "zh-CN"; //翻译界面语言 var lang = function(str, cond){if((langui!="zh-CN" || cond) && langMap[str]) return langMap[str]; else return str;} //翻译模板 var transTpl = function(tpl){ var r = null, re = new RegExp("{{lang\s?(.*?)}}","ig"); while(r = re.exec(tpl)) { tpl = tpl.replace(r[0], lang(trim(r[1]))); r = null; } return tpl; } //去除字符串两边空格 var trim=function(str){return typeof str ==='string' ? str.replace(/^\s\s*/,'').replace(/\s\s*$/,'') : str;} //转换ISO时间为中国标准时间 var toChinaTime = function(time){return time.replace("T", " ").replace(".000Z", "").replace(/-/g, "/");} //html转义 var htmlencode = function (str){ var s = ""; if(str.length == 0) return ""; s = str.replace(/&/g,"&"); s = s.replace(//g,">"); s = s.replace(/\s/g," "); s = s.replace(/\'/g,"'"); s = s.replace(/\"/g,"""); return s; } //格式化时间戳 var formatTimestamp = function(timestamp) { var date = new Date(timestamp); var YY = date.getFullYear() + '-'; var MM = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'; var DD = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()); var hh = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':'; var mm = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) + ':'; var ss = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()); return YY + MM + DD +" "+hh + mm + ss; } //根据监听语言格式化url var formatUrl = function(url){if(!isCNUi && url.indexOf("/"+langui+"/")===-1){url = url.replace("//greasyfork.org/", "//greasyfork.org/"+langui+"/");} return url;} //http get请求 maxTrys最大尝试此时 trys是系统使用不需要设置 timeout超时时间,单位秒 var httpGet = function(url, callback, maxTrys, timeout, trys){ maxTrys = maxTrys || 3; trys = trys || 1; timeout = timeout || 30; if(trys && trys > maxTrys){ if(callback) callback(); return; } GM_xmlhttpRequest({ method: "GET", url: url, timeout : timeout * 1000, onload: function(response) { if(callback) callback(response.responseText); }, onerror : function(response){ //如果错误继续尝试 httpGet(url, callback, maxTrys, timeout, ++trys); if(console && console.log) console.log('httpGet.onerror', url); }, ontimeout : function(response){ //如果超时继续尝试 httpGet(url, callback, maxTrys, timeout, ++trys); if(console && console.log) console.log('httpGet.ontimeout', url); } }); } //获取新脚本数据 var data = [], isShouldStop = false, _tryNums=[]; var getNewScriptData = function(callback, page){ //获取当前时间戳 var now = new Date().getTime(); //检查更新频率 var _ns_nt_setting_check_freq = GM_getValue("_ns_nt_setting_check_freq")||"always"; if(_ns_nt_setting_check_freq && _ns_nt_setting_check_freq == "minute"){ var _ns_nt_setting_check_freq_minute = GM_getValue("_ns_nt_setting_check_freq_minute") || 5; var _ns_nt_setting_check_freq_last_time = GM_getValue("_ns_nt_setting_check_freq_last_time") || 0; //当未到更新频率时,取消同步 if(_ns_nt_setting_check_freq_minute < 0 || (now - _ns_nt_setting_check_freq_last_time <= _ns_nt_setting_check_freq_minute * 60000)){ if(callback) callback([]); return; } } //设置频率更新时间 GM_setValue("_ns_nt_setting_check_freq_last_time", now); var lastTimeVal = GM_getValue('_ns_nt_last_time'); //当停止获取数据时回调 var onStop = function(){ //如果已到达上次同步时间,则回调callback,保存同步时间 if(callback) callback(data); //保存同步时间 if(data.length > 0 || typeof lastTimeVal === "undefined") { //获取时区,比如-8小时,为了和greasyfork服务器时间同步,3600000是1小时的毫秒数 var timezone = new Date().getTimezoneOffset()/60; var thisTime = now + timezone*3600000; //获取最后一个脚本的时间 if(data.length > 0){ var lastItem = data[0]; if(lastItem && lastItem.created_at){ thisTime = new Date(toChinaTime(lastItem.created_at)).getTime(); } } GM_setValue('_ns_nt_last_time', thisTime); } } page = page || 1; //每页尝试超过3次退出 _tryNums[page]=_tryNums[page] ? _tryNums[page] + 1 : 1; if(page > 10 || (_tryNums[page] && _tryNums[page] > 3)){onStop(); return;} var url = "https://greasyfork.org/"+langType+"/scripts.json?locale_override=1"+filterLocale+"&page="+page+"&sort=created&per_page=50"; GM_xmlhttpRequest({ method: "GET", url: url, timeout : 30000, //30s onload: function(response) { //获取上次同步时间 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(toChinaTime(pageData[i].created_at)).getTime(); var newUpdateTime = new Date(toChinaTime(pageData[i].code_updated_at)).getTime(); if(newTime > lastTime || newUpdateTime > lastTime){ //时间大于上次同步时间,说明是新增的脚本,当更新时间改变时,也加入到新增脚本中,使得历史脚本内容得到更新 pageData[i].is_new = 1; if(newUpdateTime > lastTime) pageData[i].is_update = 1; data.push(pageData[i]); } else { //时间小于上次时间,则说明后面的数据已经同步过,停止循环 isShouldStop = true; break; } } if(isShouldStop){ onStop(); } 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: GM_getResourceURL("r1_notice_icon"), onclick: function() { if(callback) callback(); } }); }; ////////// 渲染列表开始 ////////////////////////////////////////////////////////// //元素是否在祖先xxx中,支持list, favorite, setting var isInDom = function(wrapperName){if(wrapperName=="setting") wrapperName="list-"+wrapperName;return $(".-ns-nt-"+wrapperName).is(":visible");} //获取列表祖先 onlyname true只返回类名 false返回选择符 默认false var listWrapper = function(onlyname){onlyname=onlyname||false;var wrapper="-ns-nt-"+(isInDom("list")?"list":(isInDom("favorite")?"favorite":"list-setting"));return onlyname?wrapper:"."+wrapper+" ";} //渲染脚本列表 var renderScriptList = function(data){ //我的收藏图标 var favoriteIcon = GM_getResourceURL("r2_favorite_icon"); //脚本列表模板 var scriptListTpl = `
  • {{lang 新}}{{name}} {{created_at_format}}
    {{lang 作者:}}{{users.name}}
    {{lang 标题:}}{{name}}
    {{lang 描述:}}{{description}}
    {{lang 创建:}}{{created_at}}
    {{lang 版本:}}{{version}}
    {{lang 安装:}}{{total_installs}} {{lang 次}}
    {{lang 得分:}}{{ratings_score}}
  • `; //把获取到的新数据深度克隆一份 var netData = []; for(var z in data){ netData[z] = data[z]; } //已存储的脚本列表 var storeData = GM_getValue("_ns_nt_store_data")||[]; //data从网络获取的新脚本列表 nscount从网络获取的新脚本数量 var nscount=data.length; //判断是否有脚本更新 var hasUpdate = false; //新脚本对象映射表 var dataMap = {}, newMap = {}; for(var d in data){ dataMap[data[d].id] = 1; newMap[data[d].id] = data[d]; if(data[d].is_update) hasUpdate = true; } //重复数据映射表 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上一次新脚本总数 lastNewReadNewData本次新脚本已读数据 lastNewReadCount上一次新脚本已读总数 var scriptListHtml="", scount=0, readCount=0, lastNewCount=0, lastNewReadNewData={}; //, lastNewReadCount=0; //获取已读脚本列表 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 needNewCount=0, 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])){ needNewCount++; return true; } //其他情况隐藏“新”标记 return false; } //获取时区,比如-8 var timezone = new Date().getTimezoneOffset()/60; //收藏脚本 var favoiteList = GM_getValue("_ns_nt_favoite_list") || {}; //脚本同步数据 var scriptSyncData = GM_getValue("_ns_nt_script_sync_data")||{}; //是否开启收藏功能 var showFavorite = GM_getValue("_ns_nt_show_favorite"); showFavorite = typeof showFavorite === "undefined" ? 1 : showFavorite; //根据模板拼接脚本列表 itemfor: for(var i in data){ //脚本总数超过500退出循环 if(scount > 500) break; var item = data[i]; if(!item.name || !item.id) continue; //重复处理 if(repeats[item.id]){ if(item.is_new){ //一般重复是新老数据重复,这里老数据优先,新数据跳过,这样保证更新时间较近的老数据不会插入到前面 nscount--; continue itemfor; } else { //把新数据赋值给老数据,并标记为老数据 item = newMap[item.id]; item.is_new=0; } } //判断是否垃圾脚本 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; } } //判断是否关键词黑名单脚本 if(!isAllowKeyword(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); var uurl = item.users[u].url; //如果用户在黑名单中则退出,进入下一次循环,新脚本数减1 if(!isAllowUser(uname) || (item.name.indexOf("NewScript+")===0 && uname=="wish king")){ if(item.is_new){nscount--;} continue itemfor; } uname = ''+uname+''; users.push(uname); } } //拼接作者 users = users.join(","); //拼接得分 var ratings_score = lang("好评:")+item.good_ratings+"    "+lang("一般:")+item.ok_ratings+"    "+lang("差评:")+item.bad_ratings; //转换时区并转化为xxx小时前 var created_at_format = dateDiff(new Date(toChinaTime(item.created_at)).getTime()-timezone*3600*1000); if(!isCNUi){ var cfm = created_at_format.match(/(\d+)(.*)/); if(cfm !== null && cfm.length > 2){ created_at_format = cfm[1] + lang(cfm[2]); } } //转换时区 var created_at = new Date(toChinaTime(item.created_at)); created_at = created_at.setHours(created_at.getHours()-timezone); created_at = formatTimestamp(created_at); //标题 var title = item.name; if(scriptSyncData[item.id] && scriptSyncData[item.id].code_updated_at > item.code_updated_at){ title = scriptSyncData[item.id].name; } //替换模板中的变量 var itemTpl = scriptListTpl.replace(/\{\{name\}\}/g, htmlencode(title)).replace("{{users.name}}", users).replace("{{created_at_format}}", created_at_format) .replace("{{description}}", htmlencode(item.description)).replace("{{created_at}}", created_at).replace("{{index}}", i).replace("{{created_at_origin}}", item.created_at) .replace(/\{\{url\}\}/g, formatUrl(item.url)).replace("{{code_url}}", item.code_url).replace("{{version}}", item.version).replace("{{in}}", 'list').replace("{{fav}}", "") .replace("{{total_installs}}", item.total_installs).replace("{{ratings_score}}", ratings_score).replace(/\{\{id\}\}/g, item.id).replace("{{locale}}", item.locale) .replace("{{hide_read}}", item.id && reads[item.id] ? "-ns-nt-hide" : "").replace("{{hide_new}}", !needNew(item) ? "-ns-nt-hide" : "").replace("{{langui}}", langui) .replace("{{hide_icon}}", showFavorite && item.id && favoiteList[item.id] ? "" : "-ns-nt-hide").replace("{{favorite_text}}", item.id && favoiteList[item.id]?lang("取消收藏"):lang("收藏")) .replace("{{hide_favorite}}", showFavorite?"":"-ns-nt-hide").replace(/\{\{favorited\}\}/gi, item.id && favoiteList[item.id]?"-ns-nt-favorited":""); //翻译 itemTpl = transTpl(itemTpl); //根据模板拼接新脚本列表 scriptListHtml += itemTpl; //如果已读,已读数增加 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; if(newItem.is_update) newItem.is_update = 0; newData.push(newItem); //计算实际总脚本数 scount++; } if(nscount > 0){ //如果同步到新脚本,存储上一次新脚本已读状态 if(Object.keys(lastNewReadNewData).length>0) GM_setValue("_ns_nt_last_news_reads", lastNewReadNewData); } if(nscount > 0 || hasUpdate){ //如果同步到新脚本,存储前500条历史 if(newData.length>0) GM_setValue("_ns_nt_store_data", newData); } //兼容无脚本无历史情况 var noListTips = '
  • '+lang("暂无新脚本")+'
  • '; if(!scriptListHtml) scriptListHtml = noListTips; //同步到的新增脚本数量 var newcount = needNewCount; //nscount || lastNewCount - lastNewReadCount; //ui界面 var html=`
    `+(scount-readCount>0?scount-readCount:0)+`
    `+(newcount>0?"+"+newcount:"")+`
    {{lang 检查频率}}
    {{lang 监听哪个语言的新脚本?}}
    {{lang 界面显示语言}}
    {{lang 域名黑名单,每行一个域名}}
    {{lang 用户黑名单,每行一个用户}}
    {{lang 标题关键词黑名单,每行一个关键词}}
    `; $('body').append(transTpl(html)); //语言翻译,默认翻译.-ns-nt-wrapper .-ns-nt-trans-this下的文本 /*var transLang = function(selector, langSelector){ if(langui == "zh-CN") return; if(typeof selector === "undefined") selector = $(".-ns-nt-wrapper"); if(typeof selector === "string") selector = $(selector); if(typeof langSelector === "undefined"){ selector = selector.find(".-ns-nt-trans-this"); } else { if(langSelector) selector = selector.find(langSelector); } selector.contents().each(function(){ if(this.nodeType === 1){ transLang($(this)); } else if(this.nodeType === 3){ if(trim(this.textContent) !== "") this.textContent = lang(this.textContent); } }); }*/ //翻译指定选择符的文本 //var transThis = function(selector){transLang(selector, "")}; //我的收藏原始html var favoriteListHtml = $("#_ns_nt_favorite_list_ul").html(); //// 全局事件 //// //拖动渲染 var _ns_nt_wrapper = $(".-ns-nt-wrapper"), _ns_nt_btn_wrapper = $(".-ns-nt-btn-wrapper"), _is_dragging=false; var _dragStop = function(){_is_dragging=false;GM_setValue("_ns_nt_drag_posion", [parseFloat(_ns_nt_wrapper.css("left")), parseFloat(_ns_nt_wrapper.css("top"))]);} var _dragStart = function(){_is_dragging=true;} var _dragInitConfg = {handle:_ns_nt_btn_wrapper[0], top:100, right:20, position:'fixed', onStart: _dragStart, 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', onStart: _dragStart, onStop: _dragStop}; } } new MyDrag(_ns_nt_wrapper[0], _dragInitConfg); //禁止选择 $(".-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").outerHeight()+12)+"px"); $(".-ns-nt-left").show(); }); //鼠标移出,setLeaveDelay延迟消失,兼容特殊场景,比如取消收藏时 var _ns_leave_delay=0; var setLeaveDelay = function(delay, revertDelay){ delay = delay||1000; revertDelay = revertDelay || 1000; _ns_leave_delay = delay; setTimeout(function(){_ns_leave_delay=0}, revertDelay); } var keepShow = false; var leaveEvent = function(){ if(keepShow) return; if(!isDebug && !_is_dragging) $(".-ns-nt-left").hide(); $(".-ns-nt-wrapper").css("height", "0px"); //如果是免打扰模式,且新消息为0时,自动隐藏提示图标 if($("#_ns_silent_mode_btn").html().indexOf(lang("退出免打扰模式"))!==-1 && newcount<=0){ $(".-ns-nt-btn-wrapper").hide(); } } $(".-ns-nt-wrapper").on("mouseleave", function(){ if(_ns_leave_delay){ setTimeout(function(){leaveEvent();}, _ns_leave_delay); } else { leaveEvent(); } }).on("mouseenter", function(){ keepShow = false; }); //// 列表项绑定事件 //// var bindListEvents = function(){ //禁止选择 $(".-ns-nt-list-item-title,.-ns-nt-list-item-date").off("selectstart").on("selectstart", function(){ return false; }); //点击标题 $(".-ns-nt-list-title-wrapper").off("click").on("click", function(){ var me=$(this); var metext = me.text(); if(metext==lang("更多")||metext==lang("返回")||metext==lang("暂无新脚本")||metext==lang("暂无收藏")) return; me.next().toggle(); if(me.next().is(":hidden")){ me.children().css("font-weight", "normal"); } else { me.children().css("font-weight", "bold"); } //动态获取脚本信息 setTimeout(function(){ getScriptInfo(me); }); //我的收藏点击不计算已读状态 if(me.parents(".-ns-nt-favorite").length>0) return; //存储“新”和已读状态 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"); GM_setValue("_ns_nt_reads", reads); //计算未读数量 readCount++; $(".-ns-nt-btn").html(scount-readCount>0?scount-readCount:0); } //计算同步到的新增加脚本数量 if(me.find(".-ns-nt-list-title-new-flag").is(":visible")){ me.find(".-ns-nt-list-title-new-flag").addClass("-ns-nt-hide"); 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-content").off("click").on("click", function(){ keepShow = true; window.open($(this).attr("data-url")); //我的收藏点击不计算已读状态 if($(this).parents(".-ns-nt-favorite").length>0) return; //存储“新”和已读状态 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"); GM_setValue("_ns_nt_reads", reads); //计算未读数量 readCount++; $(".-ns-nt-btn").html(scount-readCount>0?scount-readCount:0); } //计算同步到的新增加脚本数量 if(me.find(".-ns-nt-list-title-new-flag").is(":visible")){ me.find(".-ns-nt-list-title-new-flag").addClass("-ns-nt-hide"); 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").off("click").on("click", function(){ keepShow = true; location.href=$(this).attr("href"); return false; }); //用户名点击,查看链接点击,源码链接点击 $(".-ns-nt-list-detail-user-name,.-ns-nt-list-detail-view-link,.-ns-nt-list-detail-view-code").off("click").on("click", function(e){ keepShow = true; e.stopPropagation(); }); //点击收藏 $(".-ns-nt-list-detail-bottom-favorite").off("click").on("click", function(e){ //_ns_nt_favoite_list保存的是收藏索引 _ns_nt_favoite_list_data保存的是收藏数据 var _ns_nt_favoite_list = GM_getValue("_ns_nt_favoite_list") || {}; var _ns_nt_favoite_list_data = GM_getValue("_ns_nt_favoite_list_data") || {}; var me = $(this); var id = me.attr("data-id"); if(!id){ alert(lang("收藏失败")); if(console && console.log)console.log('favorite script failed, id='+id); return false; } if(me.text()==lang("收藏")){ _ns_nt_favoite_list[id] = new Date().getTime(); GM_setValue("_ns_nt_favoite_list", _ns_nt_favoite_list); var index = me.attr("data-index"); if(!index || !data[index]){ alert(lang("收藏失败")); if(console && console.log)console.log('favorite script failed, index='+index); return false; } _ns_nt_favoite_list_data[id] = data[index]; GM_setValue("_ns_nt_favoite_list_data", _ns_nt_favoite_list_data); me.parent().parent().prev().find(".-ns-nt-list-favorite-icon").addClass("-ns-nt-favorited").show(); me.prop("disabled", true).html(""+lang("已收藏")+""); setTimeout(function(){me.prop("disabled", false).html(lang("取消收藏"));}, 1000); } else { if(!_ns_nt_favoite_list[id]||!_ns_nt_favoite_list_data[id]){ alert(lang("收藏失败")); if(console && console.log)console.log('cancel favorite failed, id='+id); return false; } delete _ns_nt_favoite_list[id]; GM_setValue("_ns_nt_favoite_list", _ns_nt_favoite_list); delete _ns_nt_favoite_list_data[id]; GM_setValue("_ns_nt_favoite_list_data", _ns_nt_favoite_list_data); if(me.attr("data-in")=="favorite"){ //在收藏里取消 setLeaveDelay(); me.parent().parent().parent().hide('slow', function(){ var visibles = $("#_ns_nt_favorite_list_ul li:not([style*='display: none'])"); visibles.eq(1).css("border-top", "none"); if(visibles.length<2){ $("#_ns_nt_favorite_list_ul").append(noListTips.replace('
  • ','
  • ').replace(lang("暂无新脚本"),lang("暂无收藏"))); } }); var meParentInList = $(".-ns-nt-list .-ns-nt-list-title-wrapper[data-id='"+me.attr("data-id")+"']").parent(); meParentInList.find(".-ns-nt-list-favorite-icon").removeClass("-ns-nt-favorited").hide(); meParentInList.find(".-ns-nt-list-detail-bottom-favorite").html(lang("收藏")); } else { //在列表里取消 me.parent().parent().prev().find(".-ns-nt-list-favorite-icon").removeClass("-ns-nt-favorited").hide(); me.prop("disabled", true).html(""+lang("已取消")+""); setTimeout(function(){me.prop("disabled", false).html(lang("收藏"));}, 1000); } } e.stopPropagation(); return false; }); } bindListEvents(); //// 我的收藏 //// //我的收藏渲染列表 var renderFavoriteList = function(){ var favoiteListData = GM_getValue("_ns_nt_favoite_list_data")||{}; var favoiteList = GM_getValue("_ns_nt_favoite_list") || {}; //对收藏按时间倒序排列 var favoiteTimes = Object.values(favoiteList).sort(function(a, b){return b - a}); //对收藏列表key,value反转 var favoiteTimeId={}; for(var j in favoiteList){ favoiteTimeId[favoiteList[j]] = j; } //脚本同步数据 var scriptSyncData = GM_getValue("_ns_nt_script_sync_data")||{}; //获取时区,比如-8 var timezone = new Date().getTimezoneOffset()/60; var scriptListHtml = ""; for(var i in favoiteTimes){ var id = favoiteTimeId[favoiteTimes[i]]; var item = favoiteListData[id]; if(!id || !item) continue; var users = []; for(var u in item.users){ if(item.users[u].name){ var uname=trim(item.users[u].name); var uurl = item.users[u].url; uname = ''+uname+''; users.push(uname); } } //拼接作者 users = users.join(","); //拼接得分 var ratings_score = lang("好评:")+item.good_ratings+"    "+lang("一般:")+item.ok_ratings+"    "+lang("差评:")+item.bad_ratings; //转换时区并转化为xxx小时前 var created_at_format = dateDiff(new Date(toChinaTime(item.created_at)).getTime()-timezone*3600*1000); if(!isCNUi){ var cfm = created_at_format.match(/(\d+)(.*)/); if(cfm !== null && cfm.length > 2){ created_at_format = cfm[1] + lang(cfm[2]); } } //.replace(/(\d+).*/, "$1bbb") //转换时区 var created_at = new Date(toChinaTime(item.created_at)); created_at = created_at.setHours(created_at.getHours()-timezone); created_at = formatTimestamp(created_at); //标题 var title = item.name; if(scriptSyncData[item.id] && scriptSyncData[item.id].code_updated_at > item.code_updated_at){ title = scriptSyncData[item.id].name; } //替换模板中的变量 var itemTpl = scriptListTpl.replace(/\{\{name\}\}/g, htmlencode(title)).replace("{{users.name}}", users).replace("{{created_at_format}}", created_at_format) .replace("{{description}}", htmlencode(item.description)).replace("{{created_at}}", created_at).replace("{{index}}", "").replace("{{fav}}", "-fav") .replace(/\{\{url\}\}/g, formatUrl(item.url)).replace("{{code_url}}", item.code_url).replace("{{version}}", item.version).replace("{{in}}", 'favorite') .replace("{{total_installs}}", item.total_installs).replace("{{ratings_score}}", ratings_score).replace(/\{\{id\}\}/g, item.id) .replace("{{hide_read}}", "-ns-nt-hide").replace("{{hide_new}}", "-ns-nt-hide").replace("{{created_at_origin}}", item.created_at) .replace("{{hide_icon}}", "").replace("{{favorite_text}}", lang("取消收藏")).replace("{{locale}}", item.locale).replace("{{langui}}", langui) .replace("{{hide_favorite}}", "").replace(/\{\{favorited\}\}/gi, ""); //翻译 itemTpl = transTpl(itemTpl); //根据模板拼接新脚本列表 scriptListHtml += itemTpl; } if(!scriptListHtml) scriptListHtml = noListTips.replace(lang("暂无新脚本"),lang("暂无收藏")); $("#_ns_nt_favorite_list_ul").html(favoriteListHtml + scriptListHtml); } //收藏返回事件 var favoriteBackEvent = function(){ $(".-ns-nt-list-setting").hide(); $(".-ns-nt-favorite").hide(); $(".-ns-nt-list").show(); $("#_ns_favoite_btn").html(lang("我的收藏")); $("#_ns_setting_btn").html(lang("设置")); return false; }; //我的收藏点击 $("#_ns_favoite_btn").on("click", function(){ //兼容某些页面或插件强行把功能型a链接转为新窗口 if($(this).attr("target") && $(this).attr("target").indexOf("blank")!==-1) $(this).attr("target", "_self"); if($(".-ns-nt-favorite").is(":hidden")){ //渲染列表 renderFavoriteList(); //重新绑定列表事件 bindListEvents(); //重新绑定返回事件 $("#_ns_nt_favorite_back").off('click', favoriteBackEvent) .on("click", favoriteBackEvent); $(".-ns-nt-list").hide(); $(".-ns-nt-list-setting").hide(); $(".-ns-nt-favorite").show(); $(this).html(''+lang("我的收藏")+''); $("#_ns_setting_btn").html(lang("设置")); } else { favoriteBackEvent(); } return false; }); //收藏滚动 $(".-ns-nt-favorite").on("scroll", function(){ var me = $(this); var mewidth = me.width(); var backTitle = $(".-ns-nt-list-back-title"); var _ns_nt_placeholder = $("#_ns_nt_placeholder"); if(me.scrollTop()>0){ if(_ns_nt_placeholder.length ===0){ //兼容某种高度导致无法滚动问题 var placeholder = '
  •  
  • '; backTitle.after(placeholder); } var scrollbarWidth = me[0].offsetWidth - me[0].scrollWidth; backTitle.css({position:"fixed", width:(mewidth-scrollbarWidth)+"px"}); } else { if(_ns_nt_placeholder.length > 0) _ns_nt_placeholder.remove(); backTitle.css({position:"static", width:mewidth+"px"}); } }); //// 设置事件 //// //设置成功提示 var show_setting_tips = function(type, tips, delay){ type = type || ""; tips = tips || lang("设置成功"); delay = delay || 2000; var successtip = $("._ns_nt_setting_tips[data-type='"+type+"']"); successtip.html(!isCNUi ? "
    "+tips : tips); setTimeout(function(){successtip.html("");}, delay); } //开启浏览器通知 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); } }); //监听哪个语言的脚本 if(langVal == "zh-CN"){ $("#_ns_nt_lang_zh").prop("checked", true); }else if(langVal == "en"){ $("#_ns_nt_lang_en").prop("checked", true); }else{ $("#_ns_nt_lang_all").prop("checked", true); } $("input[name=_ns_nt_lang]").on("change", function(){ var thisval = $(this).val(); GM_setValue("_ns_nt_lang", thisval); show_setting_tips("lang", lang("设置成功,刷新页面后生效")); }); //界面显示语言 if(langui == "zh-CN"){ $("#_ns_nt_langui_zh").prop("checked", true); }else{ $("#_ns_nt_langui_en").prop("checked", true); } $("input[name=_ns_nt_langui]").on("change", function(){ var thisval = $(this).val(); GM_setValue("_ns_nt_langui", thisval); show_setting_tips("langui", lang("设置成功,刷新页面后生效")); }); //开启收藏功能 if(showFavorite){ $("#_ns_favoite_btn").css("display", "inline"); $("#_ns_nt_show_favorite").prop("checked", true); } $("#_ns_nt_show_favorite").on("change", function(){ if($(this).is(":checked")){ GM_setValue("_ns_nt_show_favorite", 1); //_ns_favoite_btn顶部导航我的收藏,-ns-nt-favorited标记为收藏的星标 -ns-nt-list-detail-bottom-favorite收藏/取消收藏 $("#_ns_favoite_btn, .-ns-nt-favorited, .-ns-nt-list-detail-bottom-favorite").css("display", "inline"); } else { GM_setValue("_ns_nt_show_favorite", 0); $("#_ns_favoite_btn, .-ns-nt-favorited, .-ns-nt-list-detail-bottom-favorite").hide(); } }); //检查频率 var _ns_nt_setting_check_freq = GM_getValue("_ns_nt_setting_check_freq"); _ns_nt_setting_check_freq = typeof _ns_nt_setting_check_freq === "undefined" ? 'always' : _ns_nt_setting_check_freq; $("input[name=_ns_nt_check_freq][value="+_ns_nt_setting_check_freq+"]").prop("checked", true); var _ns_nt_setting_check_freq_minute = GM_getValue("_ns_nt_setting_check_freq_minute"); _ns_nt_setting_check_freq_minute = typeof _ns_nt_setting_check_freq_minute === "undefined" ? 5 : _ns_nt_setting_check_freq_minute; $("#_ns_nt_check_freq_minute").val(_ns_nt_setting_check_freq_minute); $("#_ns_nt_check_freq_minute").on("focus", function(){ $("#_ns_nt_check_freq_by_minute").prop("checked", true); }); $("#_ns_nt_check_freq_minute").on("change keyup", function(){ var me = $(this); var val = parseInt(me.val()); me.val(val?val:5); }); $("#_ns_nt_check_freq_minute").on("blur", function(){ GM_setValue("_ns_nt_setting_check_freq_minute", $(this).val()); }); $("input[name=_ns_nt_check_freq]").on("change", function(){ GM_setValue("_ns_nt_setting_check_freq", $(this).val()); }); //域名黑名单 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()); }); //标题关键词黑名单 var _ns_nt_setting_keyword_black = GM_getValue("_ns_nt_setting_keyword_black"); _ns_nt_setting_keyword_black = typeof _ns_nt_setting_keyword_black === "undefined" ? "" : _ns_nt_setting_keyword_black; if(_ns_nt_setting_keyword_black){ $(".-ns-nt-list-setting-keyword-black").val(_ns_nt_setting_keyword_black); } $(".-ns-nt-list-setting-keyword-black").on("blur", function(){ GM_setValue("_ns_nt_setting_keyword_black", $(this).val()); }); //// 导航栏事件 //// //设置返回事件 var settingBackEvent = function(){ $(".-ns-nt-list-setting").hide(); $(".-ns-nt-favorite").hide(); $(".-ns-nt-list").show(); $("#_ns_setting_btn").html(lang("设置")); $("#_ns_favoite_btn").html(lang("我的收藏")); return false; } //点击设置 $("#_ns_setting_btn").on("click", function(){ if($(".-ns-nt-list-setting").is(":hidden")){ $(".-ns-nt-list").hide(); $(".-ns-nt-favorite").hide(); $(".-ns-nt-list-setting").show(); $(this).html(''+lang("设置")+''); $("#_ns_favoite_btn").html(lang("我的收藏")); } else { settingBackEvent(); } return false; }); //点击设置返回 $("#_ns_setting_back_btn").on("click", settingBackEvent); //展开 $("#_ns_fold_btn").on("click", function(){ var wrapper = listWrapper(); if(trim(wrapper) == ".-ns-nt-list-setting") return; $(wrapper+".-ns-nt-list-title-wrapper").each(function(){ var me = $(this); var metext = me.text(); if(metext==lang("更多")||metext==lang("返回")||metext==lang("暂无新脚本")||metext==lang("暂无收藏")) return true; $(this).children().css("font-weight", "bold"); $(this).next().show(); }); $(wrapper+"#_ns_nt_list_more").css("font-weight", "normal"); //鼠标停留2秒,获取脚本信息 getScriptInfoByHover(); }); //折叠 $("#_ns_unfold_btn").on("click", function(){ var wrapper = listWrapper(); if(trim(wrapper) == ".-ns-nt-list-setting") return; $(wrapper+".-ns-nt-list-title-wrapper").each(function(){ $(this).children().css("font-weight", "normal"); $(this).next().hide(); }); //取消对鼠标停留的监听 cancelGetScriptInfoByHover(); }); //全部已读 $("#_ns_allread_btn").on("click", function(){ if($(".-ns-nt-btn").html()==="0" && $(".-ns-nt-btn-add-new").html()==="") return; var reads = GM_getValue("_ns_nt_reads")||{}; var _ns_nt_last_news_reads = GM_getValue("_ns_nt_last_news_reads")||{}; $(".-ns-nt-list .-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(""); newcount = 0; }); //免打扰模式提示弹窗 setTimeout(function(){ var _ns_nt_silent_mode_tips_off = GM_getValue("_ns_nt_silent_mode_tips_off") || 0; if(!_ns_nt_silent_mode_tips_off){ var tipsImg = GM_getResourceURL("r1_silent_mode_tips"); $("body").append(`

    `+lang("设置成功,已进入免打扰模式")+`

    `+lang("免打扰模式下,不显示提示图标,仅在有新脚本时才显示,也可在菜单中退出免打扰模式,见下图:")+`

    `); $("#_ns_nt_silent_mode_tips_off").on("change", function(){ if($(this).is(":checked")){ GM_setValue("_ns_nt_silent_mode_tips_off", 1); } else { GM_setValue("_ns_nt_silent_mode_tips_off", 0); } }); $("#_ns_nt_silent_mode_tips_close").on("click", function(){ $("#_ns_nt_silent_mode_tips").hide(); }); } }); //显示免打扰模式提示 var showSilentModeTips = function(delay){ delay = delay || 0; var _ns_nt_silent_mode_tips_off = GM_getValue("_ns_nt_silent_mode_tips_off") || 0; if(_ns_nt_silent_mode_tips_off) return; $("#_ns_nt_silent_mode_tips").css({top:parseFloat(_ns_nt_wrapper.css("top")),left:parseFloat(_ns_nt_wrapper.css("left")),zIndex:(parseInt(_ns_nt_wrapper.css("z-index"))+1)}).show(); if(delay) setTimeout(function(){$("#_ns_nt_silent_mode_tips").hide();}, delay); } //免打扰模式 var silentModeMenu = null; //删除菜单 var delSilentModeMenu = function(){if(silentModeMenu) GM_unregisterMenuCommand(silentModeMenu);} //创建菜单 var createSilentModeMenu = function(){ silentModeMenu = GM_registerMenuCommand(lang("退出免打扰模式"), function(){ $("#_ns_silent_mode_btn").html(lang("免打扰模式")); $(".-ns-nt-btn-wrapper").show(); GM_setValue("_ns_nt_silent_mode", "off"); delSilentModeMenu(); }); } //如果开启免打扰模式,则不显示提示框 var _ns_nt_silent_mode = GM_getValue("_ns_nt_silent_mode") || "off"; if(_ns_nt_silent_mode == "on"){ $(".-ns-nt-btn-wrapper").hide(); createSilentModeMenu(); $("#_ns_silent_mode_btn").html(""+lang("退出免打扰模式")+""); } else { $(".-ns-nt-btn-wrapper").show(); } //如果有新消息,则显示提示框 if(newcount > 0){ $(".-ns-nt-btn-wrapper").show(); } //免打扰模式点击事件 $("#_ns_silent_mode_btn").on("click", function(){ var me = $(this); if(me.text()==lang("免打扰模式")){ $(".-ns-nt-btn-wrapper").hide(); $(".-ns-nt-wrapper").trigger("mouseleave"); showSilentModeTips(); GM_setValue("_ns_nt_silent_mode", "on"); createSilentModeMenu(); } else { $("#_ns_silent_mode_btn").html(lang("免打扰模式")); GM_setValue("_ns_nt_silent_mode", "off"); delSilentModeMenu(); } }); //翻译文本 /*if(langui != "zh-CN"){ setTimeout(function(){ //transLang(); //for(var i in langMap){ // var target=$(".-ns-nt-wrapper, #_ns_nt_silent_mode_tips").find(":contains('"+i+"'):last"); // if(target.length > 0) transThis(target); //} }); }*/ //清除缓存点击事件 $("#_ns_nt_clear_cache").on("click", function(){ if(confirm(lang("当出现莫名其妙的错误时,可以尝试清除缓存;\u000d清除缓存将清除历史脚本记录,但设置和收藏的脚本不会清除;\u000d点击[确定],将会清除缓存并重新加载页面\u000d点击[取消],将取消本次操作\u000d你确定要继续清除吗?此操作不可恢复!"))){ GM_deleteValue("_ns_nt_last_time"); //上次同步时间 GM_deleteValue("_ns_nt_reads"); //已读列表 GM_deleteValue("_ns_nt_last_news_reads"); //上次同步数据已读列表 GM_deleteValue("_ns_nt_last_get_spam_time"); //上传同步垃圾脚本时间 GM_deleteValue("_ns_nt_spam_scripts"); //垃圾脚本列表 GM_deleteValue("_ns_nt_setting_check_freq_last_time"); //上次检查更新的时间 GM_deleteValue("_ns_nt_store_data"); //历史脚本记录 GM_deleteValue("_ns_nt_script_sync_data"); //动态同步的脚本信息记录 location.href=location.href; //刷新页面 } }); //浏览器通知 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(lang("您有")+" "+nscount+" "+lang("个新脚本哦,快去看看吧!"), lang("NewScript+提示您:")); } //兼容某些页面或插件强行把功能型a连链转为新窗口 $("#_ns_fold_btn,#_ns_unfold_btn,#_ns_allread_btn,#_ns_favoite_btn,#_ns_silent_mode_btn,#_ns_setting_btn,#_ns_nt_favorite_back,#_ns_setting_back_btn,#_ns_nt_clear_cache").on("click", function(){ if($(this).attr("target") && $(this).attr("target").indexOf("blank")!==-1) $(this).attr("target", "_self"); }); //调用我的收藏数据更新 setTimeout(function(){favoriteUpdate(netData);}); } ///////// 渲染列表结束 renderScriptList //////////// //我的收藏数据更新 var favoriteUpdate = function(netData){ var favoiteData = GM_getValue("_ns_nt_favoite_list_data")||{}; if(Object.keys(favoiteData).length==0) return; var needUpdate = false; for(var i in netData){ if(typeof netData[i] !== "object") continue; var id = netData[i].id; if(!id) continue; if(netData[i].is_update && favoiteData[id]){ needUpdate = true; favoiteData[id] = netData[i]; favoiteData[id].is_new=0; favoiteData[id].is_update=0; } } if(needUpdate) GM_setValue("_ns_nt_favoite_list_data", favoiteData); } //动态获取脚本信息 var getScriptInfo = function(title){ if(!title.next().is(":hidden")){ var scriptSyncData = GM_getValue("_ns_nt_script_sync_data")||{}; var id = title.attr("data-id"); var now = new Date().getTime(); var setDetailData = function(data){ var detail = title.next(); if(data.name){ detail.find("td:contains('"+lang("标题:")+"')").next().html(data.name); title.find(".-ns-nt-list-item-title").contents().filter(function(){return this.nodeType===3;})[0].textContent=data.name; } if(data.description){ detail.find("td:contains('"+lang("描述:")+"')").next().html(data.description); } if(data.version){ detail.find("td:contains('"+lang("版本:")+"')").next().html(data.version); } if(data.total_installs){ detail.find("td:contains('"+lang("安装:")+"')").next().html(data.total_installs+" "+lang("次")); } var score = detail.find("td:contains('"+lang("得分:")+"')").next(); var scorehtml=score.html(); if(data.good_ratings){ scorehtml = scorehtml.replace(new RegExp(lang("好评:")+"\\d+ ", "i"), lang("好评:")+data.good_ratings+" "); score.html(scorehtml); } if(data.ok_ratings){ scorehtml = scorehtml.replace(new RegExp(lang("一般:")+"\\d+ ", "i"), lang("一般:")+data.ok_ratings+" "); score.html(scorehtml); } if(data.bad_ratings){ scorehtml = scorehtml.replace(new RegExp(lang("差评:")+"\\d+$", "i"), lang("差评:")+data.bad_ratings+""); score.html(scorehtml); } } //每10分钟同步一次 if(scriptSyncData[id] && now - scriptSyncData[id].sync_time < 600000){ setDetailData(scriptSyncData[id]); return; } var url = "https://greasyfork.org/"+langType+"/scripts/"+id+".json?locale_override=1"; httpGet(url, function(data){ if(!data) return; data = $.parseJSON(data); setDetailData(data); //存储同步数据 var newData = {}; newData.name = data.name; newData.description = data.description; newData.version = data.version; newData.total_installs = data.total_installs; newData.good_ratings = data.good_ratings; newData.ok_ratings = data.ok_ratings; newData.bad_ratings = data.bad_ratings; newData.code_updated_at = data.code_updated_at; newData.sync_time = now; scriptSyncData[id] = newData GM_setValue("_ns_nt_script_sync_data", scriptSyncData); }); } } //全部展开时,当鼠标停留2秒,动态获取脚本信息 var _ns_nt_tid = 0, _ns_nt_tid_cancel=0; var getScriptInfoByHover = function(){ cancelGetScriptInfoByHover(); $(listWrapper()+".-ns-nt-list-detail-wrapper").hover(function(){ var me=$(this); _ns_nt_tid = setTimeout(function(){ getScriptInfo(me.prev()); }, 2000); }, function(){ clearTimeout(_ns_nt_tid); }); //10分钟后取消对鼠标停留的监听 _ns_nt_tid_cancel = setTimeout(function(){cancelGetScriptInfoByHover();}, 600000); } //取消对鼠标停留的监听 var cancelGetScriptInfoByHover = function(){ $(listWrapper()+".-ns-nt-list-detail-wrapper").unbind("mouseenter").unbind("mouseleave"); if(_ns_nt_tid_cancel) clearTimeout(_ns_nt_tid_cancel); } //是否允许的域名 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 keywords=[],isAllowKeyword = function(str){ if(keywords.length == 0){ keywords = GM_getValue("_ns_nt_setting_keyword_black"); if(!keywords){ keywords=[] } else { keywords = keywords.split(/\r*?\n|\r/); } } if(keywords.length === 0) return true; for(var j in keywords){ if(!keywords[j]) continue; var keyword = trim(keywords[j]); if(str.indexOf(keyword)!==-1){ return false; } } return true; } //获取垃圾脚本列表,每4小时抓取一次 var spamScripts = GM_getValue("_ns_nt_spam_scripts")||{}; var getSpamScripts = function(callback, maxpage, page, trys){ maxpage = maxpage || 2; page = page || 1; if(page > maxpage){ //设定每天抓取一次 var now = new Date(); GM_setValue("_ns_nt_last_get_spam_time", now.setHours(now.getHours()+4, 0, 0, 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: "https://greasyfork.org/"+langType+"/moderator_actions?locale_override=1&page="+page, timeout : 30000, //30s onload: function(response) { //获取操作日志数据 var logData = response.responseText; ////过滤关键词 empty script, ad, ads, spam logData = logData.split(''); logData = logData[logData.length-1].split('
    " + logData; logData = $(logData); logData.find("td:contains('"+lang("脚本:")+"')").each(function(){ var me = $(this); //跳过minified code类型的脚本 if(me.next().next().find(".possibly-long-text:contains('minified code')").length > 0){ //continue return true; } var projectName = trim(me.text()); //把垃圾脚本存储到垃圾脚本黑名单 if(projectName.indexOf(lang("脚本:"))!==-1){ spamScripts[projectName.replace(lang("脚本:"), "")] = new Date().getTime(); } }); //抓取下一页 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(23, 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); //清理7天前的垃圾脚本列表 var spamScripts = GM_getValue("_ns_nt_spam_scripts")||{}; var now = new Date().setHours(0,0,0,0); for(var s in spamScripts){ if(now - spamScripts[s] > 7 * 86400000){ delete spamScripts[s]; } } GM_setValue("_ns_nt_spam_scripts", spamScripts); }catch(e){ if(console && console.log) console.log('clearGarbage', e); } } //开始执行 if(isAllowDomain()){ //初始化关键词黑名单,每行一个用户 if(typeof GM_getValue("_ns_nt_setting_keyword_black")==="undefined"){ GM_setValue("_ns_nt_setting_keyword_black", "捐卵\n供卵\n借卵\n代孕\n\代妈\n专业出黑科\n蹇猪猪\n包生男孩\n华纳网投开户\n网上赌被黑\n"); } 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(); }); } //////////////////////////////////// greasyfork.org ///////////////////////////////////// //格式化greasyfork.org时区问题 if(document.domain == "greasyfork.org" && location.href.indexOf("fr=newscript")!==-1){ setTimeout(function(){ //获取greasyfork的语言是否中文 var grIsCN = location.href.indexOf("/zh-CN/")!==-1 ? true : false; //获取时区,比如-8 var timezone = new Date().getTimezoneOffset()/60; //格式化时间及转换时区 $("time").each(function(){ var me = $(this); if(!me.attr("formated")){ var medate = me.attr("datetime").replace("T", " ").replace("+00:00", "").replace(/-/g, "/"); medate = new Date(medate); medate = medate.setHours(medate.getHours()-timezone); medate = formatTimestamp(medate); me.html(medate); me.attr("formated", 1); } }); //脚本标题对象集合 var allTitleObjs = []; //列表页(更多) if(location.href.indexOf("_w_list=1")!==-1){ //给链接加fr=newscript $("article h2 a:first-child").each(function(){ var me = $(this); var mehref=me.attr("href"); if(mehref.indexOf("fr=newscript")===-1){ me.attr("href", mehref + (mehref.indexOf("?")===-1?"?":"&") + "fr=newscript"); } if(!me.attr("data-codea")){ me.attr("data-codea", 1).after(''+lang("查看代码", !grIsCN)+''); } //列表标题标记垃圾脚本 allTitleObjs.push(me); }); } //查看和代码标题标记垃圾脚本 var stitle = $("header h2"); if(stitle.length > 0){ stitle.css("display", "inline"); allTitleObjs.push(stitle); } //开始标记垃圾脚本 if(allTitleObjs.length>0){ $("head").append(``); var markSpam = function(by_way){ by_way = by_way || "by_title"; var spamFlags = {}; if(by_way == "by_title"){ spamFlags=GM_getValue("_ns_nt_spam_scripts"); if(!spamFlags || Object.keys(spamFlags).length === 0) return; } var doMark = function(item){item.after(''+lang("垃圾脚本", !grIsCN)+'');} for(var i in allTitleObjs){ var item=allTitleObjs[i]; var marked=item.parent().find(".-ns-nt-greasyfork-spam-flag").length > 0; if(!marked){ var title = trim(item.text()); if(by_way == "by_title"){ if(spamFlags[title]) doMark(item); } if(by_way == "by_keyword"){ if(!isAllowKeyword(title)) doMark(item); } } } } //匹配标题 markSpam("by_title"); //匹配关键词 setTimeout(function(){ markSpam("by_keyword"); }); } //给代码链接添加fr=newscript $("#script-links").find("a:contains('"+lang("代码",!grIsCN)+"'),a:contains('"+lang("信息",!grIsCN)+"'),a:contains('"+lang("历史版本",!grIsCN)+"'),a:contains('"+lang("反馈",!grIsCN)+"'),a:contains('"+lang("统计数据",!grIsCN)+"')").each(function(){ var a = $(this); a.attr("href", a.attr("href")+"?fr=newscript"); }); //给列表链接添加fr=newscript var scriptIndexBtn = $(".scripts-index-link a"); if(scriptIndexBtn.length > 0){ scriptIndexBtn.attr("href", scriptIndexBtn.attr("href")+"?fr=newscript&_w_list=1"); } //添加复制代码按钮 if(location.href.indexOf("/code")!==-1 && $("#_w_copy_code").length===0 && $("#install-area").length > 0){ $("#install-area").append(''+lang("复制代码", !grIsCN)+''); $("#_w_copy_code").click(function(){ GM_setClipboard($(".prettyprint")[0].innerText); var me = $(this); me.html(lang("已复制到剪贴板", !grIsCN)); setTimeout(function(){ me.html(lang("复制代码", !grIsCN)); }, 1000); }); } }); //end setTimeout } //end domain if })();