- // ==UserScript==
- // @name NodeSeek X
- // @namespace http://www.nodeseek.com/
- // @version 0.3-beta.2
- // @description 【原NodeSeek增强】自动签到、自动滚动翻页
- // @author dabao
- // @match *://www.nodeseek.com/*
- // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAACz0lEQVR4Ae3B32tVdQAA8M85u7aVHObmzJVD0+ssiphstLEM62CBlCBEIAYhUoGGD/kiRUo+9CIEElFZgZJFSApBVhCUX2WFrVQKf5Qy26SgdK4pN7eZu+cbtyfJ/gLx83HD9SAhlEyXupiPhUSTeonRfNw1ws2aRJeN5jHcolFhJJ9M8Zj99piDTnv12SjzfzIb9dmrC7Pttt8ykjDVLsu8ZZ1GH1oqeDofJLtJh4fMEw3Y72jlCuEO2+W+sNJFr3vOZ1YIi8NIGA29hDWhGgZDJ2Rt2ZvZSBazmMUsZsPZ1qwVQmcYDNWwhtAbRsNIWJx6WLPDfgxNVkm9nR8hm+XduLba7F9RtcXztmUzyY/YJrUqNPvBYc0eSS3CwXxMl4WG7CarsyEuvU2HOkRNujSw3PosxR6DFurKxx3E/akFohPo0aDfEO61os5LdrtLVWG1TzxokifdiSH9GnTjuGhBqsWE39GOo3kVi8wsmeVW00SJ200zA9r0kFcdQzv+MKElVW/S+L5EE86pmUth3BV/SzCOCUjMVXMWzfsSYybVl1SlSlESkagpuOI1nzshFX1gyAF1UKhJEKOkJFVNXVBv+pJoBK1qBkh86z1/SaR+9o5zEgoDaloxsiSart6F1Bkl83ESHWEKvvEbqZJETaokgSH9hCk6cBLtSs6kDqEb/cZ0K+MnO0X/VdhRGUBZjzH9uA+HUl+a0BvmO+J7bVZSKWz1kehqhfe9oWalNoccDmW9JnyV+toxsy3PK3aY9Gx4gMp567ziV4WawpCXra+MEhZ5xqTtecVycxzXlxA22OK4ZYbt9LjvrM5PkNUp6zVPdNpBv1QKwt126Paxp8zwqXu8kG8pYZdHlT2Rvxo2aVG2ObyYn65UnXLKVULZZrP02ZRfCms1OmAXCSHRYqrLzuZFaDFV6s/8omuERs0Kl/LzITVTvTHDeXTD9eAftAsSYhXYOWUAAAAASUVORK5CYII=
- // @require https://cdn.staticfile.org/notie/4.3.1/notie.min.js
- // @resource notieStyle https://cdn.staticfile.org/notie/4.3.1/notie.min.css
- // @resource highlightStyle https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css
- // @grant GM_xmlhttpRequest
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_deleteValue
- // @grant GM_notification
- // @grant GM_registerMenuCommand
- // @grant GM_unregisterMenuCommand
- // @grant GM_getResourceText
- // @grant GM_addElement
- // @grant GM_addStyle
- // @grant GM_openInTab
- // @grant unsafeWindow
- // @run-at document-end
- // @license GPL-3.0 License
- // @supportURL https://www.nodeseek.com/post-36263-1
- // @homepageURL https://www.nodeseek.com/post-36263-1
- // ==/UserScript==
-
- (function () {
- 'use strict';
-
- const scriptInfo = GM_info.script;
- const version = scriptInfo.version;
- const author = scriptInfo.author;
- const name = scriptInfo.name;
- const icon = scriptInfo.icon;
-
- const util = {
- clog(c) {
- console.group(`%c %c [${name}]-v${version} by ${author}`, `background:url(${icon}) center center no-repeat;background-size:12px;padding:3px`, "");
- console.log(c);
- console.groupEnd();
- },
- getValue(name) {
- return GM_getValue(name);
- },
- setValue(name, value) {
- GM_setValue(name, value);
- },
- sleep(time) {
- return new Promise((resolve) => setTimeout(resolve, time));
- },
- addStyle(id, tag, css) {
- tag = tag || 'style';
- let doc = document, styleDom = doc.getElementById(id);
- if (styleDom) return;
- let style = doc.createElement(tag);
- style.rel = 'stylesheet';
- style.id = id;
- tag === 'style' ? style.innerHTML = css : style.href = css;
- document.head.appendChild(style);
- },
- getAttributesByPrefix(element, prefix) {
- var attributes = element.attributes;
- var matchingAttributes = {};
- for (var attribute of attributes) {
- var attributeName = attribute.name;
- var attributeValue = attribute.value;
-
- if (attributeName.startsWith(prefix)) {
- matchingAttributes[attributeName] = attributeValue;
- }
- }
- return matchingAttributes;
- },
- data(element, key, value) {
- if (arguments.length < 2) {
- return undefined;
- }
- if (value != undefined) {
- element.dataset[key] = value;
- }
- return element.dataset[key];
- },
- post(url, data, headers, type) {
- if (typeof data === 'object') {
- data = JSON.stringify(data);
- }
- return new Promise((resolve, reject) => {
- GM_xmlhttpRequest({
- method: "POST", url, headers, data,
- responseType: type || 'json',
- onload: (res) => resolve(res.response || res.responseText),
- onerror: (err) => reject(err)
- });
- });
- },
- get(url, headers, type) {
- return new Promise((resolve, reject) => {
- let requestObj = GM_xmlhttpRequest({
- method: "GET", url, headers,
- responseType: type || 'json',
- onload: (res) => {
- if (res.status === 204) {
- requestObj.abort();
- }
- resolve(res.response || res.responseText);
- },
- onerror: (err) => reject(err)
- });
- });
- },
- openLinkInNewTab(selector) {
- var allLinks = document.querySelectorAll(selector);
-
- allLinks.forEach(function (link) {
- link.setAttribute('target', '_blank');
- });
- },
- getCurrentDate(){
- let localTimezoneOffset = (new Date()).getTimezoneOffset();
- let beijingOffset = 8 * 60;
- let beijingTime = new Date(Date.now() + (localTimezoneOffset + beijingOffset) * 60 * 1000);
- let timeNow = `${beijingTime.getFullYear()}/${(beijingTime.getMonth() + 1)}/${beijingTime.getDate()}`;
- return timeNow;
- }
- };
-
- const opts = {
- post: {
- pathPattern: /^\/(categories\/|page|award|search|$)/,
- scrollThreshold: 200,
- nextPagerSelector: '.nsk-pager a.pager-next',
- postListSelector: 'ul.post-list',
- topPagerSelector: 'div.nsk-pager.pager-top',
- bottomPagerSelector: 'div.nsk-pager.pager-bottom',
- },
- comment: {
- pathPattern: /^\/post-/,
- scrollThreshold: 690,
- nextPagerSelector: '.nsk-pager a.pager-next',
- postListSelector: 'ul.comments',
- topPagerSelector: 'div.nsk-pager.post-top-pager',
- bottomPagerSelector: 'div.nsk-pager.post-bottom-pager',
- },
- setting: {
- SETTING_SIGN_IN_STATUS: 'setting_sign_in_status',
- SETTING_SIGN_IN_LAST_DATE: 'setting_sign_in_last_date',
- SETTING_SIGN_IN_IGNORE_DATE: 'setting_sign_in_ignore_date'
- }
- };
-
- let main = {
- // 初始化配置数据
- initValue() {
- let value = [
- { name: opts.setting.SETTING_SIGN_IN_STATUS, defaultValue: 0 },
- { name: opts.setting.SETTING_SIGN_IN_LAST_DATE, defaultValue: '1753/1/1' },
- { name: opts.setting.SETTING_SIGN_IN_IGNORE_DATE, defaultValue: '1753/1/1' }
- ];
- this.upgradeConfig();
- value.forEach((v) => util.getValue(v.name) === undefined && util.setValue(v.name, v.defaultValue));
- },
- // 升级配置项
- upgradeConfig(){
- const upgradeConfItem=(oldConfKey,newConfKey)=>{
- if(util.getValue(oldConfKey)&&util.getValue(newConfKey)===undefined){
- util.clog(`升级配置项 ${oldConfKey} 为 ${newConfKey}`);
- util.setValue(newConfKey,util.getValue(oldConfKey));
- GM_deleteValue(oldConfKey);
- }
- };
- upgradeConfItem('menu_signInTime',opts.setting.SETTING_SIGN_IN_LAST_DATE);
- },
- loginStatus: false,
- //检查是否登陆
- checkLogin() {
- if (unsafeWindow.meCard && unsafeWindow.meCard.logined) {
- this.loginStatus = true;
- util.clog(`当前登录用户 ${unsafeWindow.meCard.user.member_name} (ID ${unsafeWindow.meCard.user.member_id})`);
- }
- },
- // 自动签到
- autoSignIn(rand) {
- if (!this.loginStatus) return
- if(util.getValue(opts.setting.SETTING_SIGN_IN_STATUS)===0) return;
-
- let timeNow = util.getCurrentDate(),
- timeOld = util.getValue(opts.setting.SETTING_SIGN_IN_LAST_DATE);
- if (!timeOld || timeOld != timeNow) { // 是新的一天
- util.setValue(opts.setting.SETTING_SIGN_IN_LAST_DATE, timeNow); // 写入签到时间以供后续比较
- this.signInRequest(rand);
- }
- },
- addSignTips() {
- if (!this.loginStatus) return
- if(util.getValue(opts.setting.SETTING_SIGN_IN_STATUS)!==0) return;
-
- const timeNow = util.getCurrentDate();
- const { SETTING_SIGN_IN_IGNORE_DATE, SETTING_SIGN_IN_LAST_DATE } = opts.setting;
- const timeIgnore = util.getValue(SETTING_SIGN_IN_IGNORE_DATE);
- const timeOld = util.getValue(SETTING_SIGN_IN_LAST_DATE);
-
- if (timeNow === timeIgnore || timeNow === timeOld) return;
-
- const _this = this;
- let tip = document.createElement('div');
- tip.className = "nsplus-tip";
- let tip_p = document.createElement('p');
- tip_p.innerHTML = '今天你还没有签到哦! 【<a class="sign_in_btn" data-rand="true" href="javascript:;">随机抽个鸡腿</a>】 【<a class="sign_in_btn" data-rand="false" href="javascript:;">只要5个鸡腿</a>】 【<a id="sign_in_ignore" href="javascript:;">今天不再提示</a>】';
- tip.appendChild(tip_p);
- tip.querySelectorAll('.sign_in_btn').forEach(function (item) {
- item.addEventListener("click", function (e) {
- const rand = util.data(this, 'rand');
- _this.signInRequest(rand);
- tip.remove();
- util.setValue(opts.setting.SETTING_SIGN_IN_LAST_DATE, timeNow); // 写入签到时间以供后续比较
- })
- });
- tip.querySelector('#sign_in_ignore').addEventListener("click", function (e) {
- tip.remove();
- util.setValue(opts.setting.SETTING_SIGN_IN_IGNORE_DATE,timeNow);
- });
-
- document.querySelector('#nsk-frame').before(tip);
- },
- signInRequest(rand) {
- util.post('/api/attendance?random=' + (rand || true), {}, { "Content-Type": "application/json" }, '').then(function (json) {
- if (json.success) {
- GM_notification({ text: '签到成功!今天午饭+' + json.gain + '个鸡腿; 积攒了' + json.current + '个鸡腿了', timeout: 3500 });
- }
- else {
- GM_notification({ text: json.message, timeout: 3500 });
- }
- }).catch(function (err) {
- util.clog(err)
- });
- util.clog(`[${name}] 签到完成`);
- },
- is_show_quick_comment: false,
- quickComment() {
- if (!this.loginStatus) return
-
- if (!opts.comment.pathPattern.test(location.pathname)) return;
- const _this = this;
- const commentDiv = document.querySelector('#fast-nav-button-group #back-to-parent').cloneNode(true);
- commentDiv.id = 'back-to-comment';
- commentDiv.innerHTML = '<svg class="iconpark-icon" style="width: 24px; height: 24px;"><use href="#comments"></use></svg>';
- commentDiv.addEventListener("click", function () {
- if (_this.is_show_quick_comment) {
- return;
- }
- const clientHeight = document.documentElement.clientHeight, clientWidth = document.documentElement.clientWidth;
- const md = document.querySelector('.md-editor');
- const mdHeight = md.clientHeight, mdWidth = md.clientWidth;
- const top = (clientHeight / 2) - (mdHeight / 2), left = (clientWidth / 2) - (mdWidth / 2);
- md.style.position = 'fixed'; md.style.top = `${top}px`; md.style.left = `${left}px`; md.style.width = '100%'; md.style.maxWidth = '720px'; md.style.zIndex = '999'; _this.addEditorCloseButton();
-
- _this.is_show_quick_comment = true;
- });
- document.querySelector('#back-to-parent').before(commentDiv);
- //document.querySelectorAll('div.comment-menu > div:nth-child(4) ').forEach(function (item) { item.onclick = function (e) { var md = document.querySelector('.md-editor'); md.style.position = 'fixed'; md.style.bottom = 0; md.style.width = '100%'; md.style.maxWidth = '720px'; md.style.zIndex = '999'; _this.addEditorCloseButton() } })
- },
- addEditorCloseButton() {
- const _this = this;
- const fullScreenToolbar = document.querySelector('#editor-body .window_header > :last-child');
- const cloneToolbar = fullScreenToolbar.cloneNode(true);
- cloneToolbar.setAttribute('title', '关闭');
- cloneToolbar.querySelector('span').classList.replace('i-icon-full-screen-one', 'i-icon-close');
- cloneToolbar.querySelector('span').innerHTML = '<svg width="16" height="16" viewBox="0 0 48 48" fill="none"><path d="M8 8L40 40" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path><path d="M8 40L40 8" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
- cloneToolbar.addEventListener("click", function (e) {
- document.querySelector('.md-editor').style = "";
- this.remove();
- _this.is_show_quick_comment = false;
- });
- fullScreenToolbar.after(cloneToolbar);
- },
- //新窗口打开帖子
- openPostInNewTab() {
- util.openLinkInNewTab('.post-title>a[href]');
- },
- //自动点击跳转页链接
- autoJump() {
- if (!/^\/jump/.test(location.pathname)) return;
- document.querySelector('.btn').click();
- },
- blockPost(ele) {
- ele = ele || document;
- ele.querySelectorAll('.post-title>a[href]').forEach(function (item) {
- if (item.textContent.toLowerCase().includes("4wl")) {
- item.closest(".post-list-item").remove()
- }
- });
- },
- //拉黑用户
- blockMemberDOMInsert() {
- if (!this.loginStatus) return;
-
- const _this = this;
- Array.from(document.querySelectorAll(".post-list .post-list-item,.content-item")).forEach((function (t, n) {
- var r = t.querySelector('.avatar-normal');
- r.addEventListener("click", (function (n) {
- n.preventDefault();
- let intervalId = setInterval(async () => {
- const userCard = document.querySelector('div.user-card.hover-user-card');
- const pmButton = document.querySelector('div.user-card.hover-user-card a.btn');
- if (userCard && pmButton) {
- clearInterval(intervalId);
- const dataVAttrs = util.getAttributesByPrefix(userCard, 'data-v');
- const userName = userCard.querySelector('a.Username').innerText;
- const blockBtn = document.createElement("a");
- for (let k in dataVAttrs) {
- blockBtn.setAttribute(k, dataVAttrs[k]);
- };
- blockBtn.onclick = function (e) { e.preventDefault(); _this.blockMember(userName) };
- blockBtn.className = "btn";
- blockBtn.style.float = "left";
- blockBtn.innerText = "拉黑";
- pmButton.after(blockBtn);
- }
- }, 50);
- }))
- }))
- },
- // 黑名单
- blockMember(userName) {
- util.post("/api/block-list/add", { "block_member_name": userName }, { "Content-Type": "application/json" }, '').then(function (data) {
- if (data.success) {
- let msg = '屏蔽用户【' + userName + '】成功!';
- unsafeWindow.mscAlert(msg);
- util.clog(msg);
- } else {
- let msg = '屏蔽用户【' + userName + '】失败!' + data.message;
- unsafeWindow.mscAlert(msg);
- util.clog(msg);
- }
- }).catch(function (err) {
- util.clog(err);
- });
- },
- addLevelTag(){//添加等级标签
- if (!this.loginStatus) return;
- if (!opts.comment.pathPattern.test(location.pathname)) return;
-
- this.getUserInfo(unsafeWindow.__config__.postData.comments[0].poster.uid,function(user){
- let span= document.createElement('span');
- span.innerHTML=`<span>Lv ${user.rank}</span>`;
- span.classList=`nsk-badge role-tag user-level user-lv${user.rank}`;
- document.querySelector('#nsk-body .nsk-post .nsk-content-meta-info .author-info>a').after(span);
- });
- },
- getUserInfo(uid,callback){
- util.get(`/api/account/getInfo/${uid}`,{},'json').then(function(data){
- if(!data.success){
- util.clog(data);
- return;
- }
- callback && callback(data.detail);
- });
- },
- // 自动翻页
- autoLoading() {
- let opt = {};
- if (opts.post.pathPattern.test(location.pathname)) { opt = opts.post; }
- else if (opts.comment.pathPattern.test(location.pathname)) { opt = opts.comment; }
- else { return; }
- let is_requesting = false;
- let _this = this;
- this.windowScroll(function (direction, e) {
- if (direction === 'down') { // 下滑才准备翻页
- let scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
- if (document.documentElement.scrollHeight <= document.documentElement.clientHeight + scrollTop + opt.scrollThreshold && !is_requesting) {
- if (!document.querySelector(opt.nextPagerSelector)) return;
- let nextUrl = document.querySelector(opt.nextPagerSelector).attributes.href.value;
- is_requesting = true;
- util.get(nextUrl, {}, 'text').then(function (data) {
- let doc = new DOMParser().parseFromString(data, "text/html");
- _this.blockPost(doc);//过滤帖子
- document.querySelector(opt.postListSelector).append(...doc.querySelector(opt.postListSelector).childNodes);
- document.querySelector(opt.topPagerSelector).innerHTML = doc.querySelector(opt.topPagerSelector).innerHTML;
- document.querySelector(opt.bottomPagerSelector).innerHTML = doc.querySelector(opt.bottomPagerSelector).innerHTML;
- history.pushState(null, null, nextUrl);
- is_requesting = false;
- }).catch(function (err) {
- is_requesting = false;
- util.clog(err);
- });
- }
- }
- });
- },
- // 滚动条事件
- windowScroll(fn1) {
- var beforeScrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop,
- fn = fn1 || function () { };
- setTimeout(function () { // 延时执行,避免刚载入到页面就触发翻页事件
- window.addEventListener('scroll', function (e) {
- var afterScrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop,
- delta = afterScrollTop - beforeScrollTop;
- if (delta == 0) return false;
- fn(delta > 0 ? 'down' : 'up', e);
- beforeScrollTop = afterScrollTop;
- }, false);
- }, 1000)
- },
- switchMultiState(stateName, states) {//多态顺序切换
- let currState = util.getValue(stateName);
- currState = (currState + 1) % states.length;
- util.setValue(stateName, currState);
- this.registerMenus();
- },
- getMenuStateText(menu, stateVal) {
- return `${menu.states[stateVal].s1} ${menu.text}(${menu.states[stateVal].s2})`;
- },
- _menus: [
- { name: opts.setting.SETTING_SIGN_IN_STATUS, callback: (name, states) => main.switchMultiState(name, states), accessKey: '', text: '自动签到', states: [{ s1: '❌', s2: '关闭' }, { s1: '🎲', s2: '随机🍗' }, { s1: '5️⃣', s2: '5个🍗' }] },
- { name: 'advanced_settings', callback: (name, states) => unsafeWindow.mscAlert('全力施工中...'), accessKey: '', text: '⚙️ 高级设置', states: [] },
- { name: 'feedback', callback: (name, states) => GM_openInTab('https://greasyfork.org/zh-CN/scripts/479426-nodeseek%E5%A2%9E%E5%BC%BA/feedback', { active: true, insert: true, setParent: true }), accessKey: '', text: '💬 反馈 & 建议', states: [] }
- ],
- _menuIds: [],
- registerMenus() {
- this._menuIds.forEach(function (id) {
- GM_unregisterMenuCommand(id);
- });
- this._menuIds = [];
-
- const _this = this;
- this._menus.forEach(function (menu) {
- let k = menu.text;
- if (menu.states.length > 0) {
- k = _this.getMenuStateText(menu, util.getValue(menu.name));
- }
- let menuId = GM_registerMenuCommand(k, function () { menu.callback(menu.name, menu.states) });
- _this._menuIds.push(menuId);
- });
- },
- addPluginStyle() {
- let style = `
- .notie-container{ opacity: 0.8; }
- .nsplus-tip { background-color: rgba(255, 217, 0, 0.8); border: 0px solid black; padding: 10px; text-align: center;animation: blink 5s cubic-bezier(.68,.05,.46,.96) infinite;}
- /* @keyframes blink{ 0%{background-color: red;} 25%{background-color: yellow;} 50%{background-color: blue;} 75%{background-color: green;} 100%{background-color: red;} } */
- .nsplus-tip p,.nsplus-tip p a { color: #f00 }
- .nsplus-tip p a:hover {color: #0ff}
- #back-to-comment{display:flex;}
- #fast-nav-button-group .nav-item-btn:nth-last-child(4){bottom:120px;}
- .post-list .post-title a:visited{color:#681da8}
- .role-tag.user-level.user-lv0 {background-color: rgb(199 194 194); border: 1px solid rgb(199 194 194); color: #fafafa;}
- .role-tag.user-level.user-lv1 {background-color: #ff9400; border: 1px solid #ff9400; color: #fafafa;}
- .role-tag.user-level.user-lv2 {background-color: #ff9400; border: 1px solid #ff9400; color: #fafafa;}
- .role-tag.user-level.user-lv3 {background-color: #ff3a55; border: 1px solid #ff3a55; color: #fafafa;}
- .role-tag.user-level.user-lv4 {background-color: #ff3a55; border: 1px solid #ff3a55; color: #fafafa;}
- .role-tag.user-level.user-lv5 {background-color: #de00ff; border: 1px solid #de00ff; color: #fafafa;}
- .role-tag.user-level.user-lv6 {background-color: #de00ff; border: 1px solid #de00ff; color: #fafafa;}
- .role-tag.user-level.user-lv7 {background-color: #ff0000; border: 1px solid #ff0000; color: #fafafa;}
- .role-tag.user-level.user-lv8 {background-color: #3478f7; border: 1px solid #3478f7; color: #fafafa;}
- `;
-
- if (document.head) {
- util.addStyle('notie-style', 'style', GM_getResourceText('notieStyle'));
- util.addStyle('nsplus-style', 'style', style);
- }
-
- const headObserver = new MutationObserver(() => {
- util.addStyle('notie-style', 'style', GM_getResourceText('notieStyle'));
- util.addStyle('nsplus-style', 'style', style);
- });
- headObserver.observe(document.head, { childList: true, subtree: true });
- },
- init() {
- this.initValue();
- this.addPluginStyle();
- this.checkLogin();
- this.autoSignIn();//自动签到
- this.addSignTips();//签到提示
- this.autoJump();//自动点击跳转页
- this.autoLoading();//无缝加载帖子和评论
- this.openPostInNewTab();//在新标签页打开帖子
- this.blockMemberDOMInsert();//拉黑用户
- this.blockPost();//屏蔽帖子
- this.quickComment();//快捷评论
- this.addLevelTag();//添加等级标签
- this.registerMenus();
- const css = GM_getResourceText("highlightStyle");
- GM_addStyle(css);
- GM_addElement('script', {
- src: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js'
- });
- GM_addElement('script', {
- textContent: 'window.onload = function(){hljs.highlightAll();}'
- });
- }
- }
- main.init();
- })();