在 GreasyFork 主頁面顯示 AI 安全檢查提示,支援多語言與網域檢查,可選啟用 Google Safe Browsing API。
当前为
// ==UserScript==
// @name GreasyFork AI Safety Checker
// @namespace http://tampermonkey.net/
// @version 2.0.3
// @description 在 GreasyFork 主頁面顯示 AI 安全檢查提示,支援多語言與網域檢查,可選啟用 Google Safe Browsing API。
// @match https://greasyfork.org/*scripts/*
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_info
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// Tampermonkey 版本檢查
const MINIMUM_TAMPERMONKEY_VERSION = '5.0.0';
if (GM_info.version < MINIMUM_TAMPERMONKEY_VERSION) {
console.warn(`Warning: Tampermonkey ${GM_info.version} is outdated, recommended: ${MINIMUM_TAMPERMONKEY_VERSION}`);
}
// 語言設定
let userLang = GM_getValue('userSelectedLanguage', navigator.language.startsWith('zh') ? 'zh-CN' : 'en');
const translations = {
'zh-CN': { safetyNotice: 'AI 安全提示:${grant} - 检查结果:${details}', /* 其他翻譯 */ },
'en': { safetyNotice: 'AI Safety Notice: ${grant} - Check Result: ${details}', /* 其他翻譯 */ }
};
function t(key, params = {}) {
let text = translations[userLang][key] || translations['en'][key];
for (const [p, v] of Object.entries(params)) text = text.replace(`\${${p}}`, v);
return text;
}
// 選單設定
let politicalCheckEnabled = GM_getValue('politicalCheckEnabled', false);
let apiCheckEnabled = GM_getValue('apiCheckEnabled', false);
GM_registerMenuCommand(politicalCheckEnabled ? '禁用政治检查' : '启用政治检查', () => {
GM_setValue('politicalCheckEnabled', !politicalCheckEnabled);
location.reload();
});
GM_registerMenuCommand(apiCheckEnabled ? '禁用 API 检查' : '启用 API 检查', () => {
GM_setValue('apiCheckEnabled', !apiCheckEnabled);
location.reload();
});
GM_registerMenuCommand('设置 Google API Key', () => {
const key = prompt('Enter Google Safe Browsing API Key');
if (key) GM_setValue('googleApiKey', key);
});
// 抓取代碼
const fetchScriptCode = () => {
const codeUrl = `${window.location.origin}${window.location.pathname}/code`;
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: codeUrl,
onload: (res) => resolve(new DOMParser().parseFromString(res.responseText, 'text/html').querySelector('pre')?.textContent || 'No code found'),
onerror: () => reject('Fetch failed')
});
});
};
// 分析腳本
const analyzeScript = async (code) => {
const matches = code.split('\n').filter(l => l.startsWith('// @match')).map(l => l.replace('// @match', '').trim());
let details = '';
if (politicalCheckEnabled) details += (await checkPoliticalRedirection(code)) || 'No political issues';
if (apiCheckEnabled) {
const apiResult = await checkDomainWithGoogle(matches[0] || window.location.host);
details += apiResult ? `; Google API: ${apiResult}` : '';
}
return t('safetyNotice', { grant: 'GM_xmlhttpRequest', details: details || 'No risks detected' });
};
// 主邏輯
fetchScriptCode().then(analyzeScript).then(warning => {
const notice = document.createElement('div');
notice.textContent = warning;
document.querySelector('.install-link')?.parentNode.insertBefore(notice, document.querySelector('.install-link'));
}).catch(console.error);
})();