├── voice_worker.js ├── LICENSE ├── .github └── workflows │ ├── sync.yml │ └── deploy.yml ├── api_worker.js ├── README.md └── free_worker.js /voice_worker.js: -------------------------------------------------------------------------------- 1 | export default { 2 | async fetch(request, env) { 3 | const url = new URL(request.url); 4 | url.host = 'voice.oaifree.com'; 5 | return fetch(new Request(url, request)); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 YX Jian 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: Upstream Sync 2 | 3 | permissions: 4 | contents: write 5 | 6 | on: 7 | schedule: 8 | - cron: "0 0 * * *" # every day 9 | workflow_dispatch: 10 | 11 | jobs: 12 | sync_latest_from_upstream: 13 | name: Sync latest commits from upstream repo 14 | runs-on: ubuntu-latest 15 | if: ${{ github.event.repository.fork }} 16 | 17 | steps: 18 | # Step 1: run a standard checkout action 19 | - name: Checkout target repo 20 | uses: actions/checkout@v3 21 | 22 | # Step 2: run the sync action 23 | - name: Sync upstream changes 24 | id: sync 25 | uses: aormsby/Fork-Sync-With-Upstream-action@v3.4 26 | with: 27 | upstream_sync_repo: jyx04/oaifree-helper 28 | upstream_sync_branch: main 29 | target_sync_branch: main 30 | target_repo_token: ${{ secrets.GITHUB_TOKEN }} # automatically generated, no need to set 31 | 32 | # Set test_mode true to run tests instead of the true action!! 33 | test_mode: false 34 | 35 | - name: Sync check 36 | if: failure() 37 | run: | 38 | echo "[Error] 由于上游仓库的 workflow 文件变更,导致 GitHub 自动暂停了本次自动更新,你需要手动 Sync Fork 一次" 39 | echo "[Error] Due to a change in the workflow file of the upstream repository, GitHub has automatically suspended the scheduled automatic update. You need to manually sync your fork." 40 | exit 1 41 | -------------------------------------------------------------------------------- /api_worker.js: -------------------------------------------------------------------------------- 1 | addEventListener('fetch', event => { 2 | const url = new URL(event.request.url); 3 | //const pathname =url.pathname; 4 | event.respondWith(handleRequest(event.request,url.pathname)); 5 | 6 | }) 7 | 8 | // @ts-ignore 9 | const KV = oai_global_variables; 10 | 11 | function parseJwt(token) { 12 | const base64Url = token.split('.')[1];// 获取载荷部分 13 | const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); 14 | const jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) { 15 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 16 | }).join('')); 17 | return JSON.parse(jsonPayload);// 返回载荷解析后的 JSON 对象 18 | } 19 | 20 | 21 | async function refreshAT(tochecktoken,an) { 22 | const accessTokenKey = `at_${an}`; 23 | const token = tochecktoken || await KV.get(accessTokenKey) ||''; 24 | if (token && token !== "Bad_RT" && token !== "Old_AT") 25 | { 26 | const payload = parseJwt(token); 27 | const currentTime = Math.floor(Date.now() / 1000); 28 | if (payload.exp > currentTime ){ 29 | return token 30 | } 31 | } 32 | const refreshTokenKey = `rt_${an}`; 33 | const url = 'https://token.oaifree.com/api/auth/refresh'; 34 | const refreshToken = await KV.get(refreshTokenKey); 35 | if (refreshToken) { 36 | // 发送 POST 请求 37 | const response = await fetch(url, { 38 | method: 'POST', 39 | headers: { 40 | 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' 41 | }, 42 | body: `refresh_token=${refreshToken}` 43 | }); 44 | 45 | // 检查响应状态 46 | if (response.ok) { 47 | const data = await response.json(); 48 | const newAccessToken = data.access_token; 49 | await KV.put(accessTokenKey, newAccessToken); 50 | return newAccessToken; 51 | } else { 52 | await KV.put(accessTokenKey, "Bad_RT"); 53 | return ''; 54 | } 55 | } 56 | else { 57 | await KV.put(accessTokenKey, "Old_AT"); 58 | return ''; 59 | } 60 | 61 | } 62 | 63 | 64 | 65 | 66 | 67 | async function handleRequest(request,pathname) { 68 | // 检查Authorization头是否包含正确的秘钥 69 | const auth = request.headers.get('Authorization'); 70 | const adminKeys = await KV.get('Admin'); 71 | const adminKeyList = adminKeys.split(','); 72 | 73 | if (!auth || !adminKeyList.includes(auth.replace('Bearer ', ''))) { 74 | return new Response('Succeed', { status: 200 }); 75 | } 76 | 77 | // 从请求中获取用户的数据 78 | const requestData = await request.json(); 79 | 80 | // 获取 aliveaccount 的值并解析 81 | const aliveAccount = await KV.get('PlusAliveAccounts'); 82 | let aliveAccountList = aliveAccount.split(','); 83 | 84 | if (aliveAccountList.length > 0) { 85 | // 从 aliveAccountList 中随机选一个 86 | const accountNumber = aliveAccountList[Math.floor(Math.random() * aliveAccountList.length)]; 87 | const newaccesstoken = await refreshAT('',accountNumber); 88 | //console.log(`Selected account number: ${accountNumber}, Access token: ${newaccesstoken}`); 89 | 90 | // 构建API请求 91 | const apiRequest = new Request(`https://api.oaifree.com${pathname}`, { 92 | method: 'POST', 93 | headers: { 94 | 'Content-Type': 'application/json', 95 | 'Authorization': `Bearer ${newaccesstoken}` 96 | }, 97 | body: JSON.stringify(requestData) 98 | }); 99 | 100 | // 发送API请求并获取响应 101 | const apiResponse = await fetch(apiRequest); 102 | const responseBody = await apiResponse.text(); 103 | 104 | 105 | // 记录响应状态和响应体 106 | //console.log(`Request: ${JSON.stringify(requestData)}`); 107 | //console.log(`Response status: ${apiResponse.status}, Response body: ${responseBody}`); 108 | 109 | if (apiResponse.status === 401) { 110 | // 如果状态码是401,从 aliveAccountList 中删除对应的序号 111 | aliveAccountList = aliveAccountList.filter(account => account !== accountNumber.toString()); 112 | await KV.put('PlusAliveAccounts', aliveAccountList.join(',')); 113 | // console.log(`Removed account number: ${accountNumber} from aliveAccountList`); 114 | await deletelog('API', accountNumber,'Plus') 115 | } 116 | 117 | // 返回API响应给用户 118 | return new Response(responseBody, { 119 | status: apiResponse.status, 120 | headers: apiResponse.headers 121 | }); 122 | } 123 | } 124 | 125 | async function deletelog(userName, accountNumber,antype) { 126 | const currentTime = new Date().toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" }); 127 | const logEntry = { 128 | user: userName, 129 | time: currentTime, 130 | accountNumber: accountNumber 131 | }; 132 | // Retrieve the existing log array or create a new one if it doesn't exist 133 | // @ts-ignore 134 | const lastDeleteLogs = await KV.get(`${antype}DeleteLogs`); 135 | let logArray = []; 136 | if (lastDeleteLogs) { 137 | logArray = JSON.parse(lastDeleteLogs); 138 | } 139 | logArray.push(logEntry); 140 | // @ts-ignore 141 | await KV.put(`${antype}DeleteLogs`, JSON.stringify(logArray)); 142 | } 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to Cloudflare Workers 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | environment: 7 | description: 'wrangler environment to deploy to' 8 | required: true 9 | default: 'dev' 10 | type: choice 11 | options: 12 | - dev 13 | - prod 14 | commit: 15 | description: 'Git commit to deploy' 16 | default: 'main' 17 | required: true 18 | 19 | push: 20 | branches: 21 | - "main" 22 | repository_dispatch: 23 | 24 | env: 25 | GIT_REF: ${{ github.event.inputs.commit || github.ref }} 26 | WORKERS_ENV: ${{ github.event.inputs.environment || 'dev' }} 27 | 28 | jobs: 29 | deploy: 30 | name: Deploy workers 31 | runs-on: ubuntu-latest 32 | steps: 33 | - name: Checkout 34 | uses: actions/checkout@v2 35 | with: 36 | ref: ${{ env.GIT_REF }} 37 | 38 | - name: Install Wrangler 39 | run: npm install -g wrangler 40 | 41 | - name: Set Cloudflare Environment Variables 42 | run: | 43 | echo "CLOUDFLARE_ACCOUNT_ID=${{ secrets.CLOUDFLARE_ACCOUNT_ID }}" >> $GITHUB_ENV 44 | echo "CLOUDFLARE_API_TOKEN=${{ secrets.CLOUDFLARE_API_TOKEN }}" >> $GITHUB_ENV 45 | 46 | - name: Validate Cloudflare Credentials 47 | run: | 48 | curl -X GET "https://api.cloudflare.com/client/v4/accounts" \ 49 | -H "Authorization: Bearer ${{ secrets.CLOUDFLARE_API_TOKEN }}" \ 50 | -H "Content-Type: application/json" 51 | 52 | - name: Create or Use Existing KV Namespace 53 | id: create_or_find_kv 54 | run: | 55 | echo "Listing KV namespaces" 56 | namespace_output=$(wrangler kv namespace list) 57 | echo "Namespace list output: $namespace_output" 58 | existing_namespace_id=$(echo "$namespace_output" | jq -r '.[] | select(.title == "oai_global_variables" or .title == "worker-oai_global_variables" or .title == "oaifreehelper-oai_global_variables" or .title == "oaifreehelper-oai_global_variables_preview" or .title == "worker-oai_global_variables_preview") | .id' | head -n 1) 59 | if [ -z "$existing_namespace_id" ]; then 60 | echo "No existing KV namespace found, creating a new one." 61 | namespace_creation_output=$(wrangler kv namespace create "oai_global_variables") || exit 1 62 | echo "Namespace creation output: $namespace_creation_output" 63 | namespace_id=$(echo "$namespace_creation_output" | grep -oP '(?<=id = ")[^"]+') 64 | echo "CF_KV_NAMESPACE_ID=$namespace_id" >> $GITHUB_ENV 65 | else 66 | echo "Found existing KV namespace with ID: $existing_namespace_id" 67 | echo "CF_KV_NAMESPACE_ID=$existing_namespace_id" >> $GITHUB_ENV 68 | fi 69 | 70 | 71 | - name: Generate wrangler.toml for main worker 72 | run: | 73 | echo "name = \"oaifreehelper\"" > wrangler.toml 74 | echo "workers_dev = true" >> wrangler.toml 75 | echo "main = \"_worker.js\"" >> wrangler.toml 76 | echo "compatibility_date = \"2024-06-01\"" >> wrangler.toml 77 | echo "[[kv_namespaces]]" >> wrangler.toml 78 | echo "binding = \"oai_global_variables\"" >> wrangler.toml 79 | echo "id = \"$CF_KV_NAMESPACE_ID\"" >> wrangler.toml 80 | 81 | - name: Publish main worker to Cloudflare Workers 82 | env: 83 | CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} 84 | run: wrangler deploy 85 | 86 | - name: Generate wrangler.toml for api worker 87 | run: | 88 | echo "name = \"api\"" > wrangler.toml 89 | echo "workers_dev = true" >> wrangler.toml 90 | echo "main = \"api_worker.js\"" >> wrangler.toml 91 | echo "compatibility_date = \"2024-06-01\"" >> wrangler.toml 92 | echo "[[kv_namespaces]]" >> wrangler.toml 93 | echo "binding = \"oai_global_variables\"" >> wrangler.toml 94 | echo "id = \"$CF_KV_NAMESPACE_ID\"" >> wrangler.toml 95 | 96 | - name: Publish api worker to Cloudflare Workers 97 | env: 98 | CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} 99 | run: wrangler deploy 100 | 101 | - name: Generate wrangler.toml for free worker 102 | run: | 103 | echo "name = \"free\"" > wrangler.toml 104 | echo "workers_dev = true" >> wrangler.toml 105 | echo "main = \"free_worker.js\"" >> wrangler.toml 106 | echo "compatibility_date = \"2024-06-01\"" >> wrangler.toml 107 | echo "[[kv_namespaces]]" >> wrangler.toml 108 | echo "binding = \"oai_global_variables\"" >> wrangler.toml 109 | echo "id = \"$CF_KV_NAMESPACE_ID\"" >> wrangler.toml 110 | 111 | - name: Publish free worker to Cloudflare Workers 112 | env: 113 | CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} 114 | run: wrangler deploy 115 | 116 | - name: Generate wrangler.toml for voice worker 117 | run: | 118 | echo "name = \"voice\"" > wrangler.toml 119 | echo "workers_dev = true" >> wrangler.toml 120 | echo "main = \"voice_worker.js\"" >> wrangler.toml 121 | echo "compatibility_date = \"2024-06-01\"" >> wrangler.toml 122 | 123 | - name: Publish api worker to Cloudflare Workers 124 | run: wrangler deploy 125 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 本项目完全依赖Linuxdo始皇大神的服务,致力于更优雅个性化访问new.oaifree站。如您无Linuxdo等级,不必浪费时间部署,本服务对您大概率无用或不好用!!! 2 | # oaifree-helper 3 | ### 本项目基于始皇的new站服务。利用单个Worker&Pages优雅访问始皇镜像站,组建合租共享车队。包含直链登陆、前端登陆页、用户管理、token池管理、车队管理、用户注册、用量查询等等功能。全程无需服务器和域名,无需改代码。 4 | 5 | # 首先,致敬始皇,致敬所有热佬,没有他们的项目和服务就没有这个项目。 6 | ### [体验站](https://oaifreehelper.haibara-ai.workers.dev) 密码linux.do,无功能,请勿填写敏感信息。 7 | ### 主要功能 8 | - 原理是储存`refreshtoken`和`accesstoken`,并调用始皇的各项接口获取`sharetoken`一键直达始皇的new.oaifree.com镜像站 9 | - 用户使用唯一用户名登陆即可后台自动分配`sharetoken`,自带始皇的聊天隔离功能。包含简易的用户体系,储存各类用户,设置各类用户的限额和限制 10 | - 支持使用/?un=xxx的直链登陆,分享更省心。 11 | - 自带注册功能,分享激活码给朋友,不用总手动录入用户 12 | - 支持组建token池,可前端面板储存token,支持自动判断rt/at,自动解析json 13 | - 支持token自动刷新,若遇at过期,自动调用始皇接口刷新at 14 | - 包含多种选车模式,可手动/指定用户专车/顺序轮询/随机选车 15 | - 支持禁用失效车次 16 | - 自动检测官方服务状态,如遇官方故障自动禁止用户登陆,甩锅官方 17 | - 支持人机验证 18 | - 点击登录页Logo跳转管理面板,包含用户管理、token池管理、用量查询、token批量导出 19 | - 支持替换Chat页面显示的头像/用户名/邮箱【新】 20 | - 支持道德审查接口【新】 21 | image 22 | image 23 | image 24 | image 25 | 26 | 27 | # Worker 部署(一键直达) 28 | [![Deploy to Cloudflare Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/jyx04/oaifree_helper) 29 | - 一键为全家桶,包含主服务/选车面板服务/API服务/反代voice服务,且无需手动关联KV,即点即用 30 | - 配置完成后,如需添加人机验证器防爆破,请按照下方Turnstile人机验证服务教程,获得`站点密钥`和`密钥` 31 | - 访问部署域名,在初始界面一键保存各项变量,完成部署! 32 | - 添加token:在登陆页点击logo,选择Token Management进入token管理面板添加 33 | # Worker 部署(手动部署) 34 | ### 1. 配置Turnstile人机验证服务(不建议跳过) 35 | - 如需跳过,后期将`RemoveTurnstile`参数设置为1即可 36 | - 注册/登陆你的cloudflare,右上角可设置语言为中文。 37 | - 左侧找到`Turnstile`,选择`添加站点` 38 | - `站点名称`随意,`域`为:`workers.dev`或你自己的域名 39 | - 创建,记录好`站点密钥`和`密钥`,备用 40 | 41 | ### 2. 部署 Cloudflare Worker: 42 | - 在左侧列表找到`Worker和Pages` 43 | - 选择`KV`,创建一个名为`oai_global_variables`的KV备用 44 | - 选择`概述`-`创建应用程序`-`Worker`,为项目命名,并创建worker 45 | - 进入`worker`-`设置`-`变量`,在`KV 命名空间绑定`添加绑定KV,变量名`oai_global_variables` 46 | - 【可选】在worker的`设置`-`触发器`-`添加自定义域`绑定自己的域名 47 | - 回到本GitHub项目,复制`_worker.js`中的全部内容,在worker配置页面点击 `编辑代码`,清空原有内容粘贴后点右上角`部署` 48 | - 大功告成! 49 | - 访问`自定义的域名`,或点击`部署`-`查看版本`,在初始面板一键保存各项环境变量(初次保存后后该页面自动禁用,若需更改请至KV中调整) 50 | 51 | ### 3. 环境变量 52 | - 以下是所有变量,全部无需手动填写,部署完项目后直接第一次进入可前端面板一键保存。 53 | - 如需进行修改,位置在KV,而非worker的环境变量! 54 | ``` 55 | Admin //管理员,用于管理面板的验证使用,且可看所有聊天记录【必填】 56 | TurnstileKeys //turnsile的密钥【必填】 57 | TurnstileSiteKey //turnsile的密钥【必填】 58 | RemoveTurnstile//跳过turnsile人机验证。设置跳过,以上两参数随便填 59 | WebName //站点名称 60 | WorkerURL //站点域名,无需https://若无自己的域名,则为worker默认域名:[worker名].[用户名].workers.dev 61 | LogoURL //图片地址,需https://,若无图床可填图片本地base64编码,不宜过大 62 | ChatLogoURL //chat界面显示的用户头像地址,需https://,若无图床可填图片本地base64编码,不宜过大 63 | ChatUserName //chat界面显示的用户名 64 | ChatMail //chat界面显示的用户邮箱 65 | 66 | Users //默认用户,以aaa,bbb,ccc形式填写,能访问所有车牌 67 | VIPUsers //vip用户,即私车用户,无速率和时间限制 68 | FreeUsers //限制用户,有速率和时间限制 69 | 70 | ForceAN //强制选车,若设置为1,用户名为xxx_n的私车用户用登陆强制进入n号车,忽略登陆所选车号 71 | SetAN //选车模式。如只有一辆车则填1。如多辆车用户手动选则留空。如需开启随机或顺序轮询,填True,并用下面两个变量控制 72 | PlusMode //plus号随机的轮询方式,Order或者Random 73 | FreeMode //普号随机的轮询方式,Order/Random或Plus(使用plus号池和配置) 74 | 75 | CDKEY //注册可用的激活码,以aaa,bbb,ccc格式 76 | AutoDeleteCDK //设置为1则激活码只可用一次 77 | FKDomain //把sharetoken当at用时,走的默认域名 78 | Status //服务状态,若为非空,无视openai官方故障通告,始终允许登陆 79 | TemporaryAN //强制启用临时聊天的车牌,以1,2,3格式 80 | 81 | //以下在管理员面板添加更方便 82 | PlusAliveAccounts //plus号池存活序号,以1,2,3格式 83 | FreeAliveAccounts //普号存活序号,以1,2,3格式 84 | rt_1 85 | rt_2 86 | at_1//(若已有rt,at可不填) 87 | at_2 88 | …… 89 | ``` 90 | 91 | ### 4. 选车面板(可选) 92 | - 通过文件`free_worker.js`部署worker,即可配置基于普号号池的选车上车界面。(一键部署已包含) 93 | - 大部分变量同上,可以额外配置以下变量 94 | ``` 95 | FreeURL //单独的URL 96 | FreeWebName //选车上车页的站点名 97 | FreeWebIntro //选车上车页的简介,可用html代码插入文本、超链接等 98 | ``` 99 | image 100 | 101 | ### 5. API接口(可选) 102 | - 通过文件`api_worker.js`部署worker,即可配置基于plus号池的api服务。(一键部署已包含) 103 | 104 | ### 6. 反代始皇的Voice服务(新增) 105 | - 通过文件`voice_worker.js`部署voice服务的反代worker。(一键部署已包含) 106 | - 需在系统KV配置变量`VoiceURL`为此worker的链接(无需https://) 107 | - 点击镜像页中间的logo,优雅访问voice服务 108 | 109 | # 使用教程 110 | ### 1. 管理面板 111 | - 配置完成后,点击登录页面的logo,可进入管理面板 112 | 113 | ### 2. Token管理 114 | - 见管理员面板的Token Management功能 115 | - 获取token:可通过[始皇的服务](https://token.oaifree.com/auth)获取普号或Plus号的rt/at(需linux.do高级用户)。也可自行通过网页获取at(自行查询教程) 116 | - 添加token:可批量输入 rt/at,以','分割,支持自动识别token类型。也可粘贴单个token的完整json,自动提取添加。添加的token将自动识别普号/plus,将序号加入对应的AliveAccountLists索引。随token添加的user为跟车用户,自动绑定车号,若设置ForceAN则强制以该车号登录。 117 | - 更新token:若存有rt,at过期将自动刷新。若无rt,将在登陆页提醒at过期 118 | - 禁用token:AliveAccountLists存有所有有效token的序号。通过账号登录页面可报告账号问题,删除序号。也可通过API调用,自动删除失效token的序号。 119 | 120 | ### 3. 批量导出号池token功能(新增) 121 | - 见管理员面板的ExportTokens功能 122 | - 可选导出Plus/Free号池 123 | - 可选生成导出链接or直接下载txt文件 124 | - txt文件格式为每行一个token,便于挪至其他服务使用 125 | 126 | ### 4. 用户和车次管理 127 | - 见管理员面板的User Management功能 128 | - 用户添加:VIPUser的有效期最长,无用量限制;User为普通用户;FreeUser为受限用户。 129 | - 用户车号选择:`SetAN`不填则用户手动选,序号则所有用户以该序号登录,True则由系统选。 130 | - 系统车号选择:当`SetAN`为True,可在`PlusMode`填入Random或Order,应用VIPUSer和User的自动选车模式。在`FreeMode`填入Random/Order或Plus,应用FreeUser的自动选车模式。Random为随机,Order为顺序,Plus为使用Plus号池和模式。 131 | 132 | ### 5. 用户注册 133 | - `CDKEY`内存有效激活码,`AutoDeleteCDK`非空则激活码只能使用一次,否则用后自动删除 134 | 135 | ### 6. 用量查询 136 | - 见管理员面板的Query User Usage功能 137 | - 若输入管理员账号,可分别查询用户和免费用户的用量,可储存和为用户名打码 138 | - 若输入非管理员账号,则查询当前用户用量 139 | 140 | ### 7. API接口(同样基于始皇的转API服务) 141 | - 本接口同样采用始皇的服务,使用plus号池内账号的token,随机调取,失效自动禁用 142 | - api的BaseURL为api worker的地址,`apikey`为admin密码,支持的服务请参考始皇的服务文档 143 | - OneAPI/NewAPI示例: 144 | - image 145 | 146 | 147 | ### 8. 接入道德审查功能(新增) 148 | - 此功能代码完全来自[Linux.do-Lvguanjun](https://linux.do/t/topic/99742),感谢大佬! 149 | - 如需启用此功能,需在KV中新增变量`ModerationApiKey`,填入始皇oaipro的apikey 150 | 151 | ### 9. 个性化和杂项 152 | - 参考以下环境变量 153 | ``` 154 | WebName //站点名称 155 | WorkerURL //站点域名,无需https://若无自己的域名,贼为worker默认域名:[worker名].[用户名].workers.dev【必填】 156 | LogoURL //图片地址,需https://,若无图床可填图片本地base64编码,不宜过大 157 | ChatLogoURL //chat界面显示的用户头像地址,需https://,若无图床可填图片本地base64编码,不宜过大 158 | ChatUesrName //chat界面显示的用户名 159 | ChatMail //chat界面显示的用户邮箱 160 | FreeWebName //选车上车页的站点名 161 | FreeWebIntro //选车上车页的简介,可用html代码插入文本、超链接等 162 | ``` 163 | - 如需修改用户的默认用量限制等,请修改worker的`getShareToken`函数,内有详细注释 164 | 165 | ### 10. 常见问题 166 | - 一些功能(如自定义头像/道德审查等),如无需使用,可在fork的项目代码内注释掉,避免聊天过程中频繁请求KV造成额度不足。 167 | - 若用量较大导致KV额度不足,建议将以上个性化参数都定义进代码,避免网页请求都频繁调用KV 168 | 169 | 170 | ### 11. About 171 | - 本服务实质是Token储存和分发,所有功能和实际服务都基于始皇大神的付出。再次向大神致敬! 172 | - Bug反馈和功能建议请在Github提交issues。故障反馈需包含log 173 | - 本项目不会收费也不会引流,个人代码能力有限,会尽力维护 174 | 175 | # 日志 176 | - 建立GitHub项目 177 | - 创建一键部署,新增选车界面和api服务 178 | - 优化用量查询功能 179 | - 新增token导出功能,可导出所选号池的rt/at为txt文件 180 | - 支持反代始皇新彩蛋:voice服务 181 | - 支持替换Chat页面显示的头像/用户名/邮箱 182 | - 新增Chat页面用户名显示车次的功能 183 | - 优化token批量导出功能和转api功能,确保at自动刷新 184 | - 支持接入道德审查接口 185 | -------------------------------------------------------------------------------- /free_worker.js: -------------------------------------------------------------------------------- 1 | addEventListener('fetch', event => { 2 | event.respondWith(handleRequest(event.request)); 3 | }); 4 | 5 | // @ts-ignore 6 | const KV = oai_global_variables; 7 | const logo = 'data:image/png;base64,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'; 8 | 9 | 10 | function parseJwt(token) { 11 | const base64Url = token.split('.')[1];// 获取载荷部分 12 | const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); 13 | const jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) { 14 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 15 | }).join('')); 16 | return JSON.parse(jsonPayload);// 返回载荷解析后的 JSON 对象 17 | } 18 | 19 | // 使用哈希函数加密username 20 | function generatePassword(token) { 21 | let hash = 7 22 | for (let i = 0; i < token.length; i++) { 23 | const char = token.charCodeAt(i) 24 | hash = (hash << 5) - hash + char 25 | hash = hash & hash // Convert to 32bit integer 26 | } 27 | // 将哈希值转换为正数,并转换为字符串 28 | let hashStr = Math.abs(hash).toString() 29 | // 如果 hashStr 长度不足 10 位,用 '7' 填充 30 | while (hashStr.length < 15) { 31 | hashStr = '7' + hashStr 32 | } 33 | // 截取前10位作为密码 34 | return hashStr.substring(0, 15) 35 | } 36 | 37 | function isTokenExpired(token) { 38 | // 检查 token 是否存在,如果不存在或为空字符串,直接返回 true 39 | if (!token || token === "Bad_RT" ||token === "Bad_AT" ) { 40 | return true; 41 | } 42 | const payload = parseJwt(token); 43 | const currentTime = Math.floor(Date.now() / 1000);// 获取当前时间戳(秒) 44 | return payload.exp < currentTime;// 检查 token 是否过期 45 | } 46 | 47 | async function getOAuthLink(shareToken, proxiedDomain) { 48 | //const url = `https://${proxiedDomain}/api/auth/oauth_token`; 49 | // 不知道为什么,好像没法直接通过反代的服务器获取oauth link 50 | const url = `https://new.oaifree.com/api/auth/oauth_token`; 51 | 52 | const response = await fetch(url, { 53 | method: 'POST', 54 | headers: { 55 | 'Origin': `https://${proxiedDomain}`, 56 | 'Content-Type': 'application/json', 57 | }, 58 | body: JSON.stringify({ 59 | share_token: shareToken 60 | }) 61 | }) 62 | const data = await response.json(); 63 | return data.login_url; 64 | } 65 | 66 | async function usermatch(userName, usertype) { 67 | const typeUsers = await KV.get(usertype) ||''; 68 | const typeUsersArray = typeUsers.split(","); // 将返回的用户类型字符串分割成数组 69 | return typeUsersArray.includes(userName); // 检查用户名是否在类型用户数组中 70 | } 71 | 72 | async function getShareToken(userName, accessToken,accountNumber) { 73 | const url = 'https://chat.oaifree.com/token/register'; 74 | /* 75 | const tokenPrefix = await KV.get('token_prefix'); 76 | const baseUserName = tokenPrefix + userName.replace(/_\d+$/, ''); // 移除用户名后的编号 77 | */ 78 | const passwd = await generatePassword(userName); 79 | const isAdmin = await usermatch(userName, 'Admin') || userName=='atdirect'; 80 | const isVIP = await usermatch(userName, 'VIPUsers') || await usermatch(userName, 'Admin') ; 81 | const isFreeUsers = await usermatch(userName, 'FreeUsers'); 82 | const isTemporary = await usermatch(accountNumber, 'TemporaryAN') && !isAdmin; 83 | 84 | 85 | //console.log(`getShareToken - userName: ${userName}, accountNumber: ${accountNumber}, showConversations: ${isAdmin}, isVIP: ${isVIP}, isTemporary: ${isTemporary}, accessToken: ${accessToken}`); 86 | const body = new URLSearchParams({ 87 | access_token: accessToken, // 使用从全局变量中获取的 accessToken 88 | unique_name: passwd, //前缀+无后缀用户名 89 | site_limit: '', // 限制的网站 90 | expires_in: isVIP ? '0' : '0', // token有效期(单位为秒),填 0 则永久有效 91 | gpt35_limit: '-1', // gpt3.5 对话限制 92 | gpt4_limit: isFreeUsers ? '-1' : '-1', // gpt4 对话限制,-1为不限制 93 | show_conversations: isAdmin ? 'true' : 'false', // 是否显示所有人的会话 94 | temporary_chat: isTemporary ? 'true' : 'false', //默认启用临时聊天 95 | show_userinfo: 'false', // 是否显示用户信息 96 | reset_limit: 'false' // 是否重置对话限制 97 | }).toString(); 98 | const apiResponse = await fetch(url, { 99 | method: 'POST', 100 | headers: { 101 | 'Content-Type': 'application/x-www-form-urlencoded' 102 | }, 103 | body: body 104 | }); 105 | const responseText = await apiResponse.text(); 106 | const tokenKeyMatch = /"token_key":"([^"]+)"/.exec(responseText); 107 | const tokenKey = tokenKeyMatch ? tokenKeyMatch[1] : 'Can not get share token.'; 108 | return tokenKey; 109 | } 110 | 111 | 112 | async function handleRequest(request) { 113 | const url = new URL(request.url); 114 | const voiceURL = await KV.get('VoiceURL'); 115 | const chatlogourl = await KV.get('ChatLogoURL') || await KV.get('LogoURL') || logo; 116 | const chatusername = await KV.get('ChatUserName') || 'Haibara AI'; 117 | const chatmail = await KV.get('ChatMail') || 'Power by Pandora'; 118 | const cookies = request.headers.get('Cookie'); 119 | let aian = ''; 120 | if (cookies) { 121 | const cookiesArray = cookies.split(';'); 122 | for (const cookie of cookiesArray) { 123 | const [name, value] = cookie.trim().split('='); 124 | if (name === 'aian') { 125 | aian = value; 126 | } 127 | } 128 | } 129 | 130 | 131 | // Specific handling for /auth/login_auth0 132 | if (url.pathname === '/auth/login_auth0') { 133 | const html = await getHTMLSelectionPage(); 134 | return new Response(html, { headers: { 'Content-Type': 'text/html' } }); 135 | 136 | } 137 | if (url.pathname === '/auth/login_auth0/login') { 138 | const params = new URLSearchParams(url.search); 139 | const encryptedAN = params.get('an'); 140 | if (request.method === 'GET') { 141 | if (encryptedAN) { 142 | if (encryptedAN == 'Random'){ 143 | const accountNumber = 'Random'; 144 | const html = await getHTMLLoginPage(accountNumber); 145 | return new Response(html, { headers: { 'Content-Type': 'text/html' } }); 146 | } 147 | else {try { 148 | const accountNumber = await decrypt(encryptedAN, 'eGJjZWFsZGVuYmVqZGZzY3VhbmZpZGZz'); //必须是32位 149 | const html = await getHTMLLoginPage(accountNumber); 150 | return new Response(html, { headers: { 'Content-Type': 'text/html' } }); 151 | } catch (e) { 152 | return new Response('Invalid account number', { status: 400 }); 153 | }} 154 | } else { 155 | const html = await getHTMLSelectionPage(); 156 | return new Response(html, { headers: { 'Content-Type': 'text/html' } }); 157 | }} 158 | if (request.method === 'POST') { 159 | return handlePostRequest(request); 160 | } 161 | } 162 | 163 | if (url.pathname === '/auth/login') { 164 | /* const token = url.searchParams.get('token'); 165 | if (!token) { 166 | if (request.method === 'GET') { 167 | return handleLoginGetRequest(request); 168 | } else if (request.method === 'POST') { 169 | return handleLoginPostRequest(request); 170 | } else { 171 | return new Response('Method not allowed', { status: 200 }); 172 | } 173 | } */ 174 | url.host = 'new.oaifree.com'; 175 | url.protocol = 'https'; 176 | return fetch(new Request(url, request)); 177 | } 178 | //Voice地址和其他 179 | url.host = 'new.oaifree.com'; 180 | url.protocol = 'https'; 181 | const modifiedRequest = new Request(url, request); 182 | if(voiceURL){ 183 | modifiedRequest.headers.set('X-Voice-Base', `https://${voiceURL}`); 184 | } 185 | const response = await fetch(modifiedRequest); 186 | 187 | //去掉小锁 188 | if (url.pathname === '/backend-api/conversations') { 189 | const data = await response.json(); 190 | data.items = data.items.filter(item => item.title !== "🔒"); 191 | return new Response(JSON.stringify(data), { 192 | status: response.status, 193 | headers: response.headers 194 | }); 195 | } 196 | 197 | //修改用户信息 198 | if (url.pathname === '/backend-api/me') { 199 | const data = await response.json(); 200 | data.picture = `${chatlogourl}`; 201 | data.email = `${chatmail}`; 202 | data.name = `${chatusername} [${aian}]`; 203 | return new Response(JSON.stringify(data), { 204 | status: response.status, 205 | headers: response.headers 206 | }); 207 | } 208 | if (url.pathname === '/backend-api/accounts/check') { 209 | const data = await response.json(); 210 | for (const accountId in data.accounts) { 211 | if (data.accounts[accountId].account) { 212 | data.accounts[accountId].account.name = `${chatusername} [${aian}]`; 213 | } 214 | } 215 | return new Response(JSON.stringify(data), { 216 | status: response.status, 217 | headers: response.headers 218 | }); 219 | } 220 | if (url.pathname === '/backend-api/gizmo_creator_profile') { 221 | const data = await response.json(); 222 | data.name = `${chatusername} [${aian}]`; 223 | data.display_name = `${chatusername} [${aian}]`; 224 | return new Response(JSON.stringify(data), { 225 | status: response.status, 226 | headers: response.headers 227 | }); 228 | } 229 | return response; 230 | } 231 | 232 | 233 | 234 | async function handlePostRequest(request) { 235 | const formData = await request.formData(); 236 | const userName = formData.get('un'); 237 | const accountNumber = formData.get('accountNumber'); 238 | const turnstileResponse = formData.get('cf-turnstile-response'); 239 | const anissues = formData.get('anissues') === 'on'; 240 | 241 | return await handleLogin(userName, accountNumber, turnstileResponse, anissues); 242 | } 243 | 244 | async function handleLogin(userName, initialaccountNumber, turnstileResponse, anissues) { 245 | //Turnsile认证 246 | if (turnstileResponse !== 'do not need Turnstle' && (!turnstileResponse || !await verifyTurnstile(turnstileResponse))) { 247 | return generateErrorResponse('Turnstile verification failed',initialaccountNumber); 248 | } 249 | const GPTState = await getGPTStatus(); 250 | const status = await KV.get('Status'); 251 | if ((GPTState == 'major_performance')&&(!status)){ 252 | await loginlog(userName, 'Bad_OAIStatus','Error'); 253 | return generateErrorResponse(`OpenAI service is under maintenance.
Official status: ${GPTState}
More details: https://status.openai.com`); 254 | } 255 | 256 | 257 | 258 | const proxiedDomain = await KV.get('FreeURL') || await KV.get('WorkerURL');//修改为反代new站的地址 259 | /* 260 | try { 261 | const tokenData = JSON.parse(userName); 262 | if (tokenData.accessToken) { 263 | const jsonAccessToken = tokenData.accessToken; 264 | const shareToken = await getShareToken('atdirect', jsonAccessToken, '0'); 265 | if (shareToken === 'Can not get share token.') { 266 | return generateErrorResponse(`Error fetching share token.`,accountNumber); 267 | } 268 | 269 | return Response.redirect(await getOAuthLink(shareToken, proxiedDomain), 302); 270 | } 271 | } catch (e) { 272 | // 输入不是 JSON 格式 273 | } 274 | 275 | 276 | // 如果输入用户名长度大于50,直接视作accessToken 277 | if (userName.length > 50) { 278 | const shareToken = await getShareToken('atdirect', userName, '0'); 279 | 280 | if (shareToken === 'Can not get share token.') { 281 | return generateErrorResponse(`Error fetching share token.`,accountNumber); 282 | } 283 | 284 | return Response.redirect(await getOAuthLink(shareToken, proxiedDomain), 302); 285 | } 286 | 287 | 288 | // 如果输入用户名fk开头,直接视作sharetoken 289 | if (userName.startsWith('fk-')) { 290 | const shareToken = userName; 291 | return Response.redirect(await getOAuthLink(shareToken, proxiedDomain), 302); 292 | } 293 | 294 | */ 295 | 296 | const userRegex = new RegExp(`^${userName}_(\\d+)$`); 297 | let fullUserName = userName; 298 | let foundSuffix = false; 299 | let accountNumber = ''; 300 | // let suffix = ''; 301 | 302 | 303 | //const freeforcecar = await KV.get("FreeForceAN"); 304 | const defaultusers = await KV.get("Users"); 305 | const vipusers = await KV.get("VIPUsers"); 306 | const freeusers = await KV.get("FreeUsers"); 307 | const admin = await KV.get("Admin"); 308 | 309 | // 合并所有用户 310 | const users = `${defaultusers},${vipusers},${freeusers},${admin}`; 311 | 312 | 313 | // 自动查找匹配的用户名格式abc_xxx,并添加后缀 314 | users.split(",").forEach(user => { 315 | const match = user.match(userRegex); 316 | if (match) { 317 | foundSuffix = true; 318 | // suffix = match[1]; // 更新后缀为实际的账号编号 319 | fullUserName = user; // 更新为完整的用户名 320 | } 321 | }); 322 | 323 | 324 | if (!foundSuffix && !users.split(",").includes(userName)) { 325 | await loginlog(userName, '404','Error'); 326 | return generateErrorResponse('Unauthorized access.',initialaccountNumber); 327 | } 328 | 329 | //禁止免费用户使用其他车 330 | const notfreeaccount = !(await usermatch(initialaccountNumber, 'FreeAliveAccounts')) && (await usermatch(fullUserName, 'Freeusers')); 331 | if (notfreeaccount) { 332 | return generateErrorResponse('Unauthorized access, please switch accounts.',initialaccountNumber); 333 | } 334 | if (initialaccountNumber =='Random'){ 335 | accountNumber = await getAccountNumber(fullUserName,'', 'Free', 'Random',anissues); 336 | } 337 | else{ 338 | accountNumber = await getAccountNumber(fullUserName,initialaccountNumber, 'Free', 'Check',anissues); 339 | } 340 | const refreshTokenKey = `rt_${accountNumber}`; 341 | const accessTokenKey = `at_${accountNumber}`; 342 | const accessToken = await KV.get(accessTokenKey); 343 | 344 | //使用佬友的sharetoken 345 | if (accessToken){ 346 | if (accessToken.startsWith('fk-')) { 347 | const fkDomain = await KV.get('FKDomain') ||proxiedDomain; 348 | //return Response.redirect(await getOAuthLink(accessToken, fkDomain), 302); 349 | return Response.redirect(`https://${fkDomain}/auth/login_share?token=${accessToken}`) 350 | } 351 | } 352 | 353 | if (isTokenExpired(accessToken)) { 354 | // 给没有refresh token的萌新用(比如我),取消下面这行注释即可享用 355 | // return generateErrorResponse('The current access token has not been updated.',accountNumber); 356 | // 如果 Token 过期,执行获取新 Token 的逻辑 357 | const url = 'https://token.oaifree.com/api/auth/refresh'; 358 | const refreshToken = await KV.get(refreshTokenKey); 359 | if (refreshToken) { 360 | 361 | // 发送 POST 请求 362 | const response = await fetch(url, { 363 | method: 'POST', 364 | headers: { 365 | 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' 366 | }, 367 | body: `refresh_token=${refreshToken}` 368 | }); 369 | 370 | // 检查响应状态 371 | if (response.ok) { 372 | const data = await response.json(); 373 | const newAccessToken = data.access_token; 374 | await KV.put(accessTokenKey, newAccessToken); 375 | } else { 376 | await KV.put(accessTokenKey, "Bad_RT"); 377 | return generateErrorResponse(`Error fetching access token.`,accountNumber); 378 | } 379 | } 380 | else { 381 | return generateErrorResponse('The current access token has not been updated.',accountNumber); 382 | } 383 | } 384 | const finalaccessToken = await KV.get(accessTokenKey); 385 | const shareToken = await getShareToken(fullUserName, finalaccessToken,accountNumber); 386 | 387 | if (shareToken === 'Can not get share token.') { 388 | //await KV.put(accessTokenKey, "Bad_AT"); 389 | return generateErrorResponse(`Error fetching share token.`,accountNumber); 390 | } 391 | 392 | 393 | // Log the successful login 394 | await loginlog(userName, accountNumber,'Free'); 395 | const oauthLink = await getOAuthLink(shareToken, proxiedDomain); 396 | const headers = new Headers(); 397 | headers.append('Location', oauthLink); 398 | headers.append('Set-Cookie', `aian=${accountNumber}; Path=/`); 399 | 400 | 401 | const response = new Response(null, { 402 | status: 302, 403 | headers: headers 404 | }); 405 | return response; 406 | 407 | } 408 | 409 | 410 | async function verifyTurnstile(responseToken) { 411 | const removeTurnstile = await KV.get('RemoveTurnstile')||''; 412 | if (removeTurnstile){return 'true'} 413 | const verifyUrl = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'; 414 | const secretKey = await KV.get('TurnstileKeys'); 415 | const response = await fetch(verifyUrl, { 416 | method: 'POST', 417 | headers: { 'Content-Type': 'application/json' }, 418 | body: JSON.stringify({ 419 | secret: secretKey, 420 | response: responseToken 421 | }) 422 | }); 423 | const data = await response.json(); 424 | return data.success; 425 | } 426 | 427 | 428 | async function loginlog(userName, accountNumber, antype) { 429 | const currentTime = new Date().toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" }); 430 | const timestamp = Date.now(); 431 | const logEntry = { 432 | user: userName, 433 | accountNumber: accountNumber, 434 | time: currentTime, 435 | timestamp: timestamp 436 | }; 437 | // Retrieve the existing log array or create a new one if it doesn't exist 438 | const lastLoginLogs = await KV.get(`${antype}LoginLogs`); 439 | let logArray = []; 440 | if (lastLoginLogs) { 441 | logArray = JSON.parse(lastLoginLogs); 442 | } 443 | logArray.push(logEntry); 444 | await KV.put(`${antype}LoginLogs`, JSON.stringify(logArray)); 445 | } 446 | 447 | async function deletelog(userName, accountNumber,antype) { 448 | const currentTime = new Date().toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" }); 449 | const logEntry = { 450 | user: userName, 451 | time: currentTime, 452 | accountNumber: accountNumber 453 | }; 454 | // Retrieve the existing log array or create a new one if it doesn't exist 455 | const lastDeleteLogs = await KV.get(`${antype}DeleteLogs`); 456 | let logArray = []; 457 | if (lastDeleteLogs) { 458 | logArray = JSON.parse(lastDeleteLogs); 459 | } 460 | logArray.push(logEntry); 461 | await KV.put(`${antype}DeleteLogs`, JSON.stringify(logArray)); 462 | } 463 | 464 | //AN获取和删除 465 | async function getAccountNumber(userName, initialaccountNumber, antype, mode, anissues) { 466 | const currentTime = Date.now() 467 | const Milliseconds = 3 * 60 * 1000; 468 | 469 | const checkAndRemoveIssueAccount = async (accountNumber) => { 470 | // Retrieve the login logs 471 | const lastLoginLogs = await KV.get(`${antype}LoginLogs`); 472 | if (lastLoginLogs) { 473 | const logArray = JSON.parse(lastLoginLogs); 474 | const userLogs = logArray.filter(log => log.user === userName && log.accountNumber === accountNumber); 475 | if (userLogs.length > 0) { 476 | const recentLogins = userLogs.filter(log => { 477 | const logTime = log.timestamp; 478 | return currentTime - logTime <= Milliseconds; 479 | }); 480 | if (recentLogins.length >= 1 && anissues) { 481 | // 删除问题账号 482 | const aliveAccount = await KV.get(`${antype}AliveAccounts`); 483 | let aliveAccountList = aliveAccount.split(','); 484 | aliveAccountList = aliveAccountList.filter(acc => acc !== accountNumber.toString()); 485 | await KV.put(`${antype}AliveAccounts`, aliveAccountList.join(',')); 486 | await deletelog(userName, accountNumber,antype); 487 | return true; 488 | } 489 | } 490 | } 491 | return false; 492 | }; 493 | 494 | // 顺序读取 495 | if (mode == 'Order') { 496 | const aliveAccountString = await KV.get(`${antype}AliveAccounts`) || ''; 497 | let aliveAccounts = aliveAccountString 498 | .split(',') 499 | .map(num => parseInt(num, 10)) 500 | .filter(num => !isNaN(num)); 501 | 502 | if (aliveAccounts.length > 0) { 503 | let minAccount = Math.min(...aliveAccounts); 504 | if (await checkAndRemoveIssueAccount(minAccount)) { 505 | aliveAccounts = aliveAccounts.filter(acc => acc !== minAccount); 506 | minAccount = aliveAccounts.length > 0 ? Math.min(...aliveAccounts) : 1; 507 | } 508 | return minAccount; 509 | } 510 | return 1; 511 | } 512 | 513 | // 检测和删除问题账号 514 | if (mode == 'Check') { 515 | await checkAndRemoveIssueAccount(initialaccountNumber); 516 | return initialaccountNumber; 517 | } 518 | 519 | // 随机读取 520 | if (mode == 'Random') { 521 | // Retrieve the last login logs 522 | const lastLoginLogs = await KV.get(`${antype}LoginLogs`); 523 | if (lastLoginLogs) { 524 | const logArray = JSON.parse(lastLoginLogs); 525 | const userLogs = logArray.filter(log => log.user === userName); 526 | const recentLogins = userLogs.filter(log => { 527 | const logTime = log.timestamp; 528 | return currentTime - logTime <= Milliseconds; 529 | }); 530 | 531 | if (recentLogins.length > 0) { 532 | const lastAccount = recentLogins[recentLogins.length - 1].accountNumber; 533 | if (await checkAndRemoveIssueAccount(lastAccount)) { 534 | const aliveAccountString = await KV.get(`${antype}AliveAccounts`) || ''; 535 | const aliveAccounts = aliveAccountString 536 | .split(',') 537 | .map(num => parseInt(num, 10)) 538 | .filter(num => !isNaN(num)); 539 | 540 | if (aliveAccounts.length > 0) { 541 | const randomAccount = aliveAccounts[Math.floor(Math.random() * aliveAccounts.length)]; 542 | return randomAccount; 543 | } 544 | return 0; 545 | } 546 | return lastAccount; 547 | } 548 | } 549 | 550 | 551 | const aliveAccountString = await KV.get(`${antype}AliveAccounts`) || ''; 552 | let aliveAccounts = aliveAccountString 553 | .split(',') 554 | .map(num => parseInt(num, 10)) 555 | .filter(num => !isNaN(num)); 556 | 557 | if (aliveAccounts.length > 0) { 558 | let randomAccount = aliveAccounts[Math.floor(Math.random() * aliveAccounts.length)]; 559 | if (await checkAndRemoveIssueAccount(randomAccount)) { 560 | aliveAccounts = aliveAccounts.filter(acc => acc !== randomAccount); 561 | if (aliveAccounts.length > 0) { 562 | randomAccount = aliveAccounts[Math.floor(Math.random() * aliveAccounts.length)]; 563 | return randomAccount; 564 | } 565 | return 0; 566 | } 567 | return randomAccount; 568 | } 569 | return 0; 570 | } 571 | 572 | return initialaccountNumber; 573 | } 574 | 575 | 576 | 577 | async function generateErrorResponse(message,accountNumber) { 578 | 579 | const errorHtml = ` 580 |
581 |
582 | 583 | ${message} 584 |
585 |
586 | `; 587 | const html = await getHTMLLoginPage(accountNumber); 588 | const responseHtml = html.replace( 589 | '', 590 | errorHtml + '' 591 | ); 592 | return new Response(responseHtml, { headers: { 'Content-Type': 'text/html' } }); 593 | } 594 | 595 | 596 | // 将密钥转换为 CryptoKey 对象 597 | async function getCryptoKey(secret) { 598 | return crypto.subtle.importKey( 599 | 'raw', 600 | new TextEncoder().encode(secret), 601 | 'AES-GCM', 602 | false, 603 | ['encrypt', 'decrypt'] 604 | ); 605 | } 606 | 607 | // 加密函数 608 | async function encrypt(text, secret) { 609 | const iv = crypto.getRandomValues(new Uint8Array(12)); // 初始化向量 610 | const key = await getCryptoKey(secret); 611 | const encrypted = await crypto.subtle.encrypt( 612 | { 613 | name: 'AES-GCM', 614 | iv: iv 615 | }, 616 | key, 617 | new TextEncoder().encode(text) 618 | ); 619 | 620 | // 返回 base64 编码的 iv 和加密结果 621 | return btoa(String.fromCharCode(...iv)) + ':' + btoa(String.fromCharCode(...new Uint8Array(encrypted))); 622 | } 623 | 624 | // 解密函数 625 | async function decrypt(encryptedText, secret) { 626 | const [iv, data] = encryptedText.split(':').map(part => Uint8Array.from(atob(part), c => c.charCodeAt(0))); 627 | const key = await getCryptoKey(secret); 628 | const decrypted = await crypto.subtle.decrypt( 629 | { 630 | name: 'AES-GCM', 631 | iv: iv 632 | }, 633 | key, 634 | data 635 | ); 636 | 637 | return new TextDecoder().decode(decrypted); 638 | } 639 | 640 | async function getGPTStatus(){ 641 | const url = 'https://status.openai.com/api/v2/summary.json'; 642 | 643 | 644 | // 发送 POST 请求 645 | const response = await fetch(url, { 646 | method: 'GET', 647 | headers: { 648 | 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' 649 | }, 650 | }); 651 | // 检查响应状态 652 | if (response.ok) { 653 | const data = await response.json(); 654 | const status = data.components.find((component) => component.name === 'ChatGPT'); 655 | //return JSON.stringify(status); 656 | return status.status; 657 | } 658 | else {return 'operational';} 659 | } 660 | 661 | async function getHTMLSelectionPage() { 662 | const aliveAccounts = await KV.get('FreeAliveAccounts') || ''; 663 | const aliveAccountsArray = aliveAccounts.split(',').map(num => num.trim()).filter(num => num !== ''); 664 | const websiteName = await KV.get('FreeWebName') || await KV.get('WebName') || 'Haibara AI'; 665 | const introContent = await KV.get('FreeWebIntro') || ''; 666 | 667 | const options = await Promise.all(aliveAccountsArray.map(async (accountNumber) => { 668 | const encryptedAN = await encrypt(accountNumber, 'eGJjZWFsZGVuYmVqZGZzY3VhbmZpZGZz'); // 必须是32位 669 | return ` 670 |
671 | 672 | 673 |
674 | `; 675 | })); 676 | 677 | return ` 678 | 679 | 680 | 681 | 682 | 683 | ${websiteName} 684 | 685 | 686 | 687 | 854 | 861 | 869 | 870 | 871 | 872 |
873 |

${websiteName}

874 |
875 |
876 | ${introContent ? ` 877 |
878 | ${introContent} 879 |
` : ''} 880 | 881 |
882 | 883 | 884 | 887 |
888 |
889 | 890 | 893 | 894 | 895 | `; 896 | } 897 | 898 | 899 | async function getHTMLLoginPage(accountNumber) { 900 | const logourl = await KV.get('LogoURL') || logo; 901 | const WorkerURL=await KV.get('WorkerURL'); 902 | const turnstileSiteKey=await KV.get('TurnstileSiteKey'); 903 | const websiteName = await KV.get('FreeWebName') || await KV.get('WebName') || 'Haibara AI'; 904 | const removeTurnstile = await KV.get('RemoveTurnstile')||''; 905 | return ` 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | Free - ${websiteName} 915 | 1277 | 1278 | 1279 | 1280 |
1281 |
1282 |
1283 | 1284 | Logo 1285 | 1286 |
1287 |
1288 |
1289 |

${websiteName}

1290 | 1319 |
1320 |
1321 |
1322 |
1323 | 1358 | 1359 | 1360 | 1361 | `; 1362 | } 1363 | 1364 | --------------------------------------------------------------------------------