├── 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 |
22 |
23 |
24 |
25 |
26 |
27 | # Worker 部署(一键直达)
28 | [](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 |
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 | -
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 |
Don't have an account? Sign Up
1318 |