// ==UserScript== // @name ChatGPT Helper // @namespace https://linux.do/u/f-droid // @version 1.1 // @description 一站式ChatGPT增强工具,支持Access Token获取、服务降级检测等功能 // @license GNU Affero General Public License v3.0 or later // @author F-Droid // @match https://chatgpt.com/* // @match https://new.oaifree.com/* // @match https://*.new.oaifree.com/* // @match https://shared.oaifree.com/* // @icon https://linux.do/user_avatar/linux.do/f-droid/288/228666_2.png // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @run-at document-end // @downloadURL none // ==/UserScript== (function() { 'use strict'; const currentUrl = window.location.href; if (!( currentUrl.startsWith('https://chatgpt.com/') || currentUrl.startsWith('https://new.oaifree.com/') || currentUrl.startsWith('https://shared.oaifree.com/') || currentUrl.match(/^https:\/\/(?:[^\/]+\.)?new\.oaifree\.com\//) )) { return; } const panel = document.createElement('div'); panel.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 350px; background: linear-gradient(145deg, #f8f9fa, #e9ecef); border-radius: 15px; box-shadow: 0 15px 35px rgba(0,0,0,0.1), 0 5px 15px rgba(0,0,0,0.05); padding: 20px; z-index: 10001; font-family: 'Inter', 'Segoe UI', Arial, sans-serif; color: #2c3e50; transition: all 0.3s ease; display: none; `; const titleBar = document.createElement('div'); titleBar.innerHTML = `

ChatGPT Helper

`; panel.appendChild(titleBar); const statusSection = document.createElement('div'); statusSection.innerHTML = `
服务降级检测
PoW难度: N/A
这个值越小,代表PoW难度越高,ChatGPT认为你的IP风险越高。
IP质量: N/A
`; panel.appendChild(statusSection); const tokenSection = document.createElement('div'); tokenSection.innerHTML = `
Access Token Tool
`; panel.appendChild(tokenSection); const createToast = (message) => { const toast = document.createElement('div'); toast.innerText = message; toast.style.cssText = ` position: fixed; bottom: 20px; right: 20px; background: rgba(76, 175, 80, 0.9); color: white; border-radius: 8px; padding: 10px 20px; box-shadow: 0 5px 15px rgba(0,0,0,0.3); font-family: 'Inter', 'Segoe UI', Arial, sans-serif; z-index: 10001; transition: opacity 0.5s ease; `; document.body.appendChild(toast); setTimeout(() => { toast.style.opacity = '0'; setTimeout(() => { document.body.removeChild(toast); }, 500); }, 1000); }; const ball = document.createElement('div'); const getFavicon = () => { const favicon = document.querySelector("link[rel~='icon']") || document.querySelector("link[rel='shortcut icon']") || document.querySelector("link[rel='icon']"); if (favicon) { const faviconUrl = favicon.href; ball.style.backgroundImage = `url(${faviconUrl})`; ball.style.backgroundSize = 'cover'; ball.style.backgroundPosition = 'center'; } else { ball.style.backgroundColor = 'rgba(0, 123, 255, 0.8)'; } }; ball.style.cssText = ` position: fixed; top: 25%; right: 20px; width: 40px; height: 40px; border-radius: 50%; cursor: pointer; z-index: 10000; box-shadow: 0 4px 6px rgba(0,0,0,0.1); transition: transform 0.2s; `; getFavicon(); ball.addEventListener('mouseenter', () => { ball.style.transform = 'scale(1.1)'; }); ball.addEventListener('mouseleave', () => { ball.style.transform = 'scale(1)'; }); document.body.appendChild(ball); ball.onclick = () => { panel.style.display = panel.style.display === 'none' ? 'block' : 'none'; }; let isDragging = false; let currentX; let currentY; let initialX; let initialY; let xOffset = 0; let yOffset = 0; const dragStart = (e) => { initialX = e.type === 'mousedown' ? e.clientX - xOffset : e.touches[0].clientX - xOffset; initialY = e.type === 'mousedown' ? e.clientY - yOffset : e.touches[0].clientY - yOffset; if (e.target === titleBar) { isDragging = true; } }; const drag = (e) => { if (isDragging) { e.preventDefault(); currentX = e.type === 'mousemove' ? e.clientX - initialX : e.touches[0].clientX - initialX; currentY = e.type === 'mousemove' ? e.clientY - initialY : e.touches[0].clientY - initialY; xOffset = currentX; yOffset = currentY; setTranslate(currentX, currentY, panel); } }; const dragEnd = () => { initialX = currentX; initialY = currentY; isDragging = false; }; const setTranslate = (xPos, yPos, el) => { el.style.transform = `translate(-50%, -50%) translate(${xPos}px, ${yPos}px)`; }; titleBar.addEventListener('mousedown', dragStart); titleBar.addEventListener('touchstart', dragStart); document.addEventListener('mousemove', drag); document.addEventListener('touchmove', drag); document.addEventListener('mouseup', dragEnd); document.addEventListener('touchend', dragEnd); document.body.appendChild(panel); const tokenDisplay = document.getElementById('token-display'); const closeBtn = document.getElementById('close-btn'); const fetchBtn = document.getElementById('fetch-btn'); const copyBtn = document.getElementById('copy-btn'); fetchBtn.onclick = function() { GM_xmlhttpRequest({ method: "GET", url: "/api/auth/session", onload: function(response) { try { const data = JSON.parse(response.responseText); tokenDisplay.value = data.accessToken || '获取失败'; } catch(e) { tokenDisplay.value = '获取失败:' + e.message; } }, onerror: function() { tokenDisplay.value = '网络错误,请重试'; } }); }; copyBtn.onclick = function() { if (tokenDisplay.value) { GM_setClipboard(tokenDisplay.value); createToast('Access Token已复制到剪贴板'); } }; closeBtn.onclick = function() { panel.style.display = 'none'; }; const updateDifficultyIndicator = (difficulty) => { const difficultyLevel = document.getElementById('difficulty-level'); const ipQuality = document.getElementById('ip-quality'); if (difficulty === 'N/A') { difficultyLevel.innerText = ''; ipQuality.innerHTML = 'N/A'; return; } const cleanDifficulty = difficulty.replace('0x', '').replace(/^0+/, ''); const hexLength = cleanDifficulty.length; let level, qualityText, color; if (hexLength <= 2) { level = '(困难)'; qualityText = '高风险'; color = '#FF0000'; } else if (hexLength === 3) { level = '(中等)'; qualityText = '中等'; color = '#FFA500'; } else if (hexLength === 4) { level = '(简单)'; qualityText = '良好'; color = '#FFFF00'; } else { level = '(极易)'; qualityText = '优秀'; color = '#00FF00'; } difficultyLevel.innerHTML = `${level}`; ipQuality.innerHTML = `${qualityText}`; }; const originalFetch = window.fetch; window.fetch = async function(resource, options) { try { const response = await originalFetch(resource, options); const url = typeof resource === 'string' ? resource : resource.url; if (url.includes('/backend-api/sentinel/chat-requirements') || url.includes('/backend-anon/sentinel/chat-requirements')) { GM_xmlhttpRequest({ method: "POST", url: url, headers: options?.headers, data: options?.body, onload: function(response) { try { const data = JSON.parse(response.responseText); const difficulty = data.proofofwork?.difficulty || 'N/A'; document.getElementById('difficulty').innerText = difficulty; updateDifficultyIndicator(difficulty); } catch(e) { console.error('解析响应时出错:', e); } } }); } return response; } catch(e) { console.error('请求拦截时出错:', e); return originalFetch(resource, options); } }; const initCheck = () => { GM_xmlhttpRequest({ method: "POST", url: "/backend-api/sentinel/chat-requirements", headers: { "Content-Type": "application/json" }, data: JSON.stringify({}), onload: function(response) { try { const data = JSON.parse(response.responseText); const difficulty = data.proofofwork?.difficulty || 'N/A'; document.getElementById('difficulty').innerText = difficulty; updateDifficultyIndicator(difficulty); } catch(e) { console.error('初始化检查时出错:', e); } } }); }; setTimeout(initCheck, 2000); const footer = document.createElement('div'); footer.style.marginTop = '15px'; footer.style.textAlign = 'center'; footer.innerHTML = `Copyright © ${new Date().getFullYear()} F-Droid retain all rights reserved.
如果您喜欢这个工具,请给作者点个赞吧!😊`; panel.appendChild(footer); })();