chatgpt-access-token-pool

随手写了个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

这熟悉的代码

6 Likes

熟悉的味道。

5 Likes

还是一样的配方

2 Likes

大佬玩转closeai!

1 Like

V 佬继续整活:ox::beer:

2 Likes

支持个

来一个一呼百应的佬,比如甘佬

1 Like

支持

我们需要成品 哈哈哈

这个怎么用?

cf 中转一下能感觉到慢下来了

稍微改了下,暂时没用那个upload的方式上传token所以去掉那个方法了

  1. 增加了自己的token池子
  2. 增加了简单的对token的次数限制
  3. 每天晚上12点重置token的次数限制,现在默认是200每个token
  4. 增加了防呆URL, 我自己用了lobe发现会有这个问题,其余的没测试
  5. 增加判断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

佬应该怎么使用啊……头有点大,自动通过re-token刷新se-token么?

好好好,worker还不太会用,又遇到了新的知识

Sk是自己定义的token不用刷新,你想设置复杂点就自己搞个jwt的出去,自动刷新的是gpt自己的token

1 Like

不明觉厉

From #develop:ai to #share