Greasy Fork is available in English.
NodeSeek论坛增强脚本
当前为
// ==UserScript==
// @name 星渊NS助手
// @namespace https://www.nodeseek.com/
// @version 0.1.1
// @description NodeSeek论坛增强脚本
// @author stardeep
// @license GPL-3.0
// @match https://www.nodeseek.com/*
// @icon https://drstth.com/download/favicon.ico
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_info
// @grant unsafeWindow
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
console.log('[NS助手] 脚本开始加载');
const CONFIG_URL = 'https://raw.githubusercontent.com/stardeep925/NSaide/main/modules/config.json';
const CACHE_EXPIRY = 30 * 60 * 1000;
const CACHE_KEY_PREFIX = 'ns_module_cache_';
const CONFIG_CACHE_KEY = 'ns_config_cache';
const getCachedData = (key) => {
const cached = GM_getValue(key);
if (!cached) return null;
try {
const { data, timestamp } = JSON.parse(cached);
if (Date.now() - timestamp > CACHE_EXPIRY) {
GM_setValue(key, '');
return null;
}
return data;
} catch {
return null;
}
};
const setCachedData = (key, data) => {
GM_setValue(key, JSON.stringify({
data,
timestamp: Date.now()
}));
};
const fetchWithCache = (url, cacheKey) => {
return new Promise((resolve, reject) => {
const cached = getCachedData(cacheKey);
if (cached) {
console.log(`[NS助手] 使用缓存数据: ${cacheKey}`);
resolve(cached);
return;
}
GM_xmlhttpRequest({
method: 'GET',
url: `${url}?t=${Date.now()}`,
nocache: true,
headers: {
'Cache-Control': 'no-cache',
'Pragma': 'no-cache'
},
onload: (response) => {
if (response.status === 200) {
try {
const data = response.responseText;
setCachedData(cacheKey, data);
resolve(data);
} catch (error) {
reject(error);
}
} else {
reject(new Error(`请求失败: ${response.status}`));
}
},
onerror: reject
});
});
};
const loadConfig = async () => {
try {
const configText = await fetchWithCache(CONFIG_URL, CONFIG_CACHE_KEY);
return JSON.parse(configText);
} catch (error) {
console.error('[NS助手] 配置加载失败:', error);
throw error;
}
};
const loadModule = async (moduleInfo) => {
const cacheKey = `${CACHE_KEY_PREFIX}${moduleInfo.id}`;
try {
console.log(`[NS助手] 开始加载模块: ${moduleInfo.name}`);
const moduleCode = await fetchWithCache(moduleInfo.url, cacheKey);
eval(moduleCode);
console.log(`[NS助手] 模块加载成功: ${moduleInfo.name}`);
} catch (error) {
console.error(`[NS助手] 模块 ${moduleInfo.name} 加载失败:`, error);
throw error;
}
};
const createNS = () => {
window.NS = {
version: GM_info.script.version,
modules: new Map(),
isReady: false,
registerModule(moduleDefinition) {
if (!moduleDefinition || !moduleDefinition.id || !moduleDefinition.init) return;
const module = {
...moduleDefinition,
enabled: GM_getValue(`module_${moduleDefinition.id}_enabled`, true)
};
this.modules.set(moduleDefinition.id, module);
console.log(`[NS助手] 模块已注册: ${module.name}`);
},
init() {
if (this.isReady) return;
const enabledModules = Array.from(this.modules.values()).filter(m => m.enabled);
console.log(`[NS助手] 开始初始化 ${enabledModules.length} 个已启用模块`);
Promise.all(enabledModules.map(module =>
new Promise(resolve => {
try {
module.init();
console.log(`[NS助手] 模块初始化成功: ${module.name}`);
resolve();
} catch (error) {
console.error(`[NS助手] 模块 ${module.name} 初始化失败:`, error);
resolve();
}
})
)).then(() => {
this.isReady = true;
console.log('[NS助手] 所有模块初始化完成');
});
}
};
window.NSRegisterModule = (moduleDefinition) => {
window.NS.registerModule(moduleDefinition);
};
};
const initializeModules = async () => {
try {
createNS();
const config = await loadConfig();
await Promise.all(config.modules.map(loadModule));
if (window.NS.modules.size > 0) {
window.NS.init();
}
} catch (error) {
console.error('[NS助手] 初始化失败:', error);
}
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeModules);
} else {
initializeModules();
}
})();