// ==UserScript== // @name ChatGPT AccessToken 自动更新 // @namespace http://tampermonkey.net/ // @version 2.7 // @description 根据token过期时间自动获取accessToken并发送POST请求后自动跳转到new.oaifree.com // @author AMT // @match *://new.oaifree.com/* // @grant GM_xmlhttpRequest // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @connect chatgpt.com // @connect new.oaifree.com // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 定义获取accessToken的URL const tokenUrl = "https://chatgpt.com/api/auth/session"; // 定义POST请求的目标URL const postUrl = "https://new.oaifree.com/auth/login_token"; // 定义跳转的目标URL const redirectUrl = "https://new.oaifree.com"; // 定义GM存储的key const expiresKey = 'tokenExpires'; // 保存token过期时间的key // 获取当前时间的时间戳(毫秒) let currentTime = new Date().getTime(); // 将延迟时间存储到GM存储中 let delay = GM_getValue('delay', 60000); // 从GM存储获取token过期时间 let expires = GM_getValue(expiresKey, 0); // 计算距离token过期的时间 function calculateTimeUntilExpiry() { currentTime = new Date().getTime(); const timeUntilExpiry = expires - currentTime; // 计算剩余时间的各个部分 const daysUntilExpiry = Math.floor(timeUntilExpiry / (24 * 60 * 60 * 1000)); const hoursUntilExpiry = Math.floor((timeUntilExpiry % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000)); const minutesUntilExpiry = Math.floor((timeUntilExpiry % (60 * 60 * 1000)) / (60 * 1000)); const secondsUntilExpiry = Math.floor((timeUntilExpiry % (60 * 1000)) / 1000); // 返回各个部分的时间和秒数 return { daysUntilExpiry, hoursUntilExpiry, minutesUntilExpiry, secondsUntilExpiry }; } // Base64URL 解码 function base64UrlDecode(str) { return decodeURIComponent(atob(str.replace(/-/g, '+').replace(/_/g, '/')).split('').map(function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); } // 解析 JWT function parseJWT(token) { const parts = token.split('.'); if (parts.length !== 3) { console.error('Invalid JWT token'); return null; } const payload = JSON.parse(base64UrlDecode(parts[1])); // 仅解析payload部分 return payload; } //刷新时间 // 创建可视化窗口 const panel = document.createElement('div'); panel.id = 'script-panel'; const { daysUntilExpiry, hoursUntilExpiry, minutesUntilExpiry } = calculateTimeUntilExpiry(); panel.innerHTML = `

距离AccessToken过期还有:

`; document.body.appendChild(panel); updateDisplay() // 添加样式 GM_addStyle(` #script-panel { position: fixed; top: 10%; right: 0; width: 300px; background-color: rgba(0, 0, 0, 0.7); color: white; padding: 15px; border-radius: 10px 0 0 10px; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); z-index: 10000; transform: translateX(98%); transition: transform 0.5s ease-in-out; cursor: move; } #panel-content { display: block; text-align: center; } #script-panel:hover { transform: translateX(0); } #run-script-button { background-color: #4CAF50; color: white; border: none; padding: 10px 15px; text-align: center; text-decoration: none; display: inline-block; font-size: 14px; margin: 10px 0; cursor: pointer; border-radius: 5px; transition: background-color 0.3s, box-shadow 0.1s; } #run-script-button:hover { background-color: #45a049; } #run-script-button:active { box-shadow: inset 0px 3px 5px rgba(0, 0, 0, 0.2); background-color: #39843b; } `); // 添加拖动功能 let isDragging = false; let startY = 0; let startTop = 0; panel.addEventListener('mousedown', function(e) { isDragging = true; startY = e.clientY; startTop = panel.offsetTop; document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); }); function onMouseMove(e) { if (isDragging) { const deltaY = e.clientY - startY; panel.style.top = `${startTop + deltaY}px`; } } function onMouseUp() { isDragging = false; document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', onMouseUp); } function updateDisplay() { const { daysUntilExpiry, hoursUntilExpiry, minutesUntilExpiry, secondsUntilExpiry } = calculateTimeUntilExpiry(); let displayText = ""; if (daysUntilExpiry > 0) { displayText += `${daysUntilExpiry}天`; } if (hoursUntilExpiry > 0 ) { displayText += `${hoursUntilExpiry}小时`; } if (minutesUntilExpiry > 0 ) { displayText += `${minutesUntilExpiry}分钟`; } if (daysUntilExpiry === 0 && hoursUntilExpiry === 0 && minutesUntilExpiry === 0) { displayText = `${secondsUntilExpiry}秒`; if (delay !=1000) { delay = 1000; // 设置为每秒刷新一次 GM_setValue('delay', delay); } } document.getElementById('time-until-expiry').textContent = displayText; } // 添加时间自动更新功能 setInterval(() => { updateDisplay(); if (shouldFetchToken()) { fetchAndPostToken(); } }, delay); // 添加按钮点击事件 document.getElementById('run-script-button').addEventListener('click', function() { fetchAndPostToken(); }); // 检查是否需要获取token if (shouldFetchToken()) { fetchAndPostToken(); } else { console.log("Script not run: Token is still valid."); } // 判断是否需要获取token function shouldFetchToken() { currentTime = new Date().getTime(); return currentTime > expires; } // 获取token并发送POST请求的函数 function fetchAndPostToken() { GM_xmlhttpRequest({ method: "GET", url: tokenUrl, onload: function(response) { if (response.status === 200) { // 解析返回的JSON const responseData = JSON.parse(response.responseText); // 提取accessToken const accessToken = responseData.accessToken; // 解析JWT获取过期时间 const parsedToken = parseJWT(accessToken); if (parsedToken && parsedToken.exp) { const tokenExpires = parsedToken.exp * 1000; // 将exp转换为毫秒 // 更新过期时间 GM_setValue(expiresKey, tokenExpires); GM_setValue('delay', 60000); // 发送POST请求 sendPostRequest(accessToken, tokenExpires); } else { console.error("Failed to parse JWT token or exp not found."); } } else { console.error("Failed to fetch accessToken. Status:", response.status); } } }); } // 发送POST请求的函数 function sendPostRequest(accessToken, tokenExpires) { const data = { action: "token", access_token: accessToken }; GM_xmlhttpRequest({ method: "POST", url: postUrl, headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: Object.keys(data).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`).join('&'), onload: function(response) { console.log("Status Code:", response.status); console.log("Response:", response.responseText); // 成功发送POST请求后自动跳转 if (response.status === 200) { window.location.href = redirectUrl; } }, onerror: function(error) { console.error("Error in POST request:", error); } }); } })();