随手写了个cloudflare work 的demo,做pool来用
有能力帮忙改改
addEventListener('fetch', event => {
const url = new URL(event.request.url);
if (url.pathname === '/upload') {
event.respondWith(handleUpload(event.request));
} else if (url.pathname === '/v1/chat/completions') {
event.respondWith(handleRequest(event.request));
} else {
event.respondWith(new Response('Not Found', { status: 404 }));
}
})
const KV = chatgpt_access_pool;
async function handleRequest(request) {
// 检查Authorization头是否包含正确的秘钥
const auth = request.headers.get('Authorization');
if (!auth || auth !== 'Bearer sk-123') {
return new Response('Secret Unauthorized', { status: 401 });
}
// 从请求中获取用户的数据
const requestData = await request.json();
// 从KV数据库中随机获取一个键的值
const keys = await KV.list();
const randomKey = keys.keys[Math.floor(Math.random() * keys.keys.length)];
const randomValue = await KV.get(randomKey.name);
// 从值中提取access_token
const access_token = JSON.parse(randomValue).access_token;
console.log(access_token)
// 构建API请求
const apiRequest = new Request('https://api.oaifree.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${access_token}`
},
body: JSON.stringify(requestData)
});
// 发送API请求并获取响应
const apiResponse = await fetch(apiRequest);
// 返回API响应给用户
return apiResponse;
}
async function handleUpload(request) {
// 从上传请求中获取邮箱和JSON数据
const uploadData = await request.json();
// 检查email和access_token是否为空
if (!uploadData.email && !uploadData.access_token) {
return new Response('email and access_token cannot be empty', { status: 400 });
}
await KV.put(uploadData.email, JSON.stringify(uploadData));
// 返回一个表示成功的响应给用户
return new Response('Upload successful', { status: 200 });
}
29 Likes
paderlol
(一只猪🐷)
13
稍微改了下,暂时没用那个upload的方式上传token所以去掉那个方法了
- 增加了自己的token池子
- 增加了简单的对token的次数限制
- 每天晚上12点重置token的次数限制,现在默认是200每个token
- 增加了防呆URL, 我自己用了lobe发现会有这个问题,其余的没测试
- 增加判断token到期前三天刷新token
TODO:
每天定时减少access_token的有效时间
const accessPool = chatgptAccessPool;
const skUsers = sk_user;
const apiUrls = ['/v1/chat/completions',
'/v1/chat/completions/chat/completions'];
addEventListener('fetch', event => {
const url = new URL(event.request.url);
const { method } = event.request;
if (method === 'POST' && apiUrls.includes(url.pathname)) {
event.respondWith(handleRequest(event.request));
} else {
event.respondWith(new Response('Not Found', { status: 404 }));
}
});
async function handleScheduled(event) {
const users = await skUsers.list({ prefix: 'sk-' });
if (users.keys.length === 0) {
return new Response('ok');
}
for (let i = 0; i < users.keys.length; i++) {
let key = users.keys[i].name;
await skUsers.put(key, 200);
}
return new Response('ok');
}
addEventListener('scheduled', event => {
event.waitUntil(handleScheduled(event));
});
async function handleRequest(request) {
// 检查Authorization头是否包含正确的秘钥
const auth = request.headers.get('authorization');
if (!auth && !auth.startsWith('Bearer ')) {
return new Response('Secret Unauthorized', { status: 401 });
}
let token = auth.substring(7);
// 从auth里面拿到Bearer后面的秘钥
let credit = await skUsers.get(token);
if (credit == null) {
return new Response('Secret Unauthorized', { status: 401 });
} else if (credit <= 0) {
return new Response('Credit was not enough', { status: 500 });
}
skUsers.put(token, credit - 1);
// 从请求中获取用户的数据
const requestData = await request.json();
// 从KV数据库中随机获取一个键的值
const keys = await accessPool.list();
if (keys.keys.length === 0) {
return new Response('No keys available', { status: 500 });
}
let randomKey = keys.keys[0];
if (keys.keys.length > 1) {
randomKey = keys.keys[Math.floor(Math.random() * keys.keys.length)];
}
const accessInfo = await accessPool.get(randomKey.name, { type: 'json' });
// 从值中提取access_token
let access_token = accessInfo.access_token;
const expire_time = accessInfo.expires_in;
// 如果expire_time 小于3天,则重新获取access_token
if (expire_time < 259200) {
const refresh_token = accessInfo.refresh_token;
let formData = new FormData();
formData.append('refresh_token', refresh_token);
const refreshRequest = new Request(
'https://token.oaifree.com/api/auth/refresh',
{
method: 'POST',
body: formData
});
const refreshResponse = await fetch(refreshRequest);
const refreshData = await refreshResponse.json();
access_token = refreshData.access_token;
await accessPool.put(randomKey.name, JSON.stringify(refreshData));
}
const apiRequest = new Request(
'https://api.oaifree.com/v1/chat/completions',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${access_token}`
},
body: JSON.stringify(requestData)
});
// 发送API请求并获取响应
const apiResponse = await fetch(apiRequest);
console.log(JSON.stringify(apiResponse));
// 返回API响应给用户
return apiResponse;
}
6 Likes
BenSu
14
佬应该怎么使用啊……头有点大,自动通过re-token刷新se-token么?
paderlol
(一只猪🐷)
16
Sk是自己定义的token不用刷新,你想设置复杂点就自己搞个jwt的出去,自动刷新的是gpt自己的token
1 Like
neo
(Neo)
Category updated
18
From #develop:ai to #share