如题,佬友 @yangtb2024
真的是太热心了
从今天早上到现在,一直耐心和小白解答问题
包括serv00部署的new-api如何调用gemini最新模型
还有serv00部署的new-api不支持长文本的问题,也解决了
这个佬友花了好长时间不厌其烦解答,无敌了
如题,佬友 @yangtb2024
真的是太热心了
从今天早上到现在,一直耐心和小白解答问题
包括serv00部署的new-api如何调用gemini最新模型
还有serv00部署的new-api不支持长文本的问题,也解决了
这个佬友花了好长时间不厌其烦解答,无敌了
发一面赛博锦旗
@yangtb2024 感谢佬友!
@前后注意空格,不然@不到
良好的论坛风气
学会了
可以说是配享太庙啊 从早上到现在 哭了
感谢佬友,佬友才是真的好啊
你学会了,可以教会更多的佬友
例如我赛博文盲
可以的应该?
这种友好互助、无私奉献的氛围真的太棒了,在当今这个浮躁的互联网时代,站内的这种氛围犹如冬夜里的暖阳
再次感谢佬不厌其烦解答
不支持长文本啥意思?看图中貌似你是全站开启了Under Attack
(不建议),然后WAF设置了跳过规则,其实你需要跳过的路径还很多
就是用serv00部署的new-api,域名我的是托管在cloudflare上面的,但是默认情况下(指你没做任何waf操作),你输入长文本(token数量比如3500以上4000以上),他就会返回错误
如图
短文本token数少的,就正常回复
例如长文本代码,500多行的
// Configuration
const CACHE_DURATION_MINUTES = 50;//对话缓存时间 min
const CHECK_PERIOD_MINUTES = 240; //繁忙复位时间 min
const RETENTION_PERIOD_MINUTES = 240;
const BASE_URL = 'https://claude.asia';
const AUTH_ENDPOINT = '/manage-api/auth/oauth_token';
const CACHE_KEY = 'login_urls_cache';
// Convert minutes to milliseconds
const CACHE_DURATION_MS = CACHE_DURATION_MINUTES * 60 * 1000;
const CHECK_PERIOD_MS = CHECK_PERIOD_MINUTES * 60 * 1000;
const RETENTION_PERIOD_MS = RETENTION_PERIOD_MINUTES * 60 * 1000;
// Status constants
const STATUS = {
BUSY: { color: 'busy', status: '繁忙' },
FREE: { color: 'free', status: '空闲' }
};
//放SESSION_KEYS的地方,带引号,一行一个
const SESSION_KEYS = [
// [email protected]
'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',
// [email protected] (新加坡三网)
'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',
// [email protected] (日本ijj)
'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',
// 共享的 keys
'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',
'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',
'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'
];
async function getLoginUrl(sessionKey) {
try {
const response = await fetch(`${BASE_URL}${AUTH_ENDPOINT}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
session_key: sessionKey,
unique_name: Date.now().toString()
}),
});
const data = await response.json();
if (data.login_url) {
return data.login_url.startsWith('http')
? data.login_url
: `${BASE_URL}${data.login_url}`;
}
} catch (error) {
console.error("Login URL Error:", error);
}
return '#';
}
async function getAccountStatus(accountNumber, env) {
const key = `clicks_${accountNumber}`;
const currentTime = Date.now();
try {
const clicks = await env.CLAUDE_KV.get(key, 'json') || [];
const recentClicks = clicks.filter(time => (currentTime - time) < CHECK_PERIOD_MS);
return recentClicks.length >= 1 ? STATUS.BUSY : STATUS.FREE;
} catch (error) {
console.error("Status Error:", error);
return STATUS.FREE;
}
}
async function updateClickTime(accountNumber, env) {
const key = `clicks_${accountNumber}`;
const currentTime = Date.now();
try {
const clicks = await env.CLAUDE_KV.get(key, 'json') || [];
const recentClicks = clicks.filter(time => (currentTime - time) < RETENTION_PERIOD_MS);
recentClicks.push(currentTime);
await env.CLAUDE_KV.put(key, JSON.stringify(recentClicks));
} catch (error) {
console.error("Update Click Error:", error);
}
}
async function generateHTML(loginUrls, accountStatuses) {
return `<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>远大港湾</title>
<style>
body, html {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
margin: 0;
padding: 0;
min-height: 100vh;
background: linear-gradient(135deg, #ffffff, #f0f0f0);
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 0;
}
h1, h2 {
color: #2c3e50;
margin: 0;
}
.accounts {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
gap: 15px;
margin: 30px 0;
}
.account {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 80px;
text-decoration: none;
padding: 12px 8px;
border-radius: 12px;
font-size: 0.95rem;
transition: all 0.3s ease;
border: 1px solid rgba(0,0,0,0.1);
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.account.free {
background-color: #81c784;
color: #1b5e20;
}
.account.busy {
background-color: #ef9a9a;
color: #c62828;
}
.account:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.account span {
margin-top: 5px;
font-size: 0.85rem;
opacity: 0.9;
}
footer {
margin-top: 40px;
padding-top: 20px;
border-top: 1px solid #eee;
text-align: center;
color: #666;
}
@media (max-width: 768px) {
.accounts {
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.account {
min-height: 70px;
padding: 10px 5px;
}
}
</style>
<script>
function updateStatus(accountNumber, event) {
event.preventDefault();
const link = event.currentTarget;
const url = link.href;
fetch('?clicked=' + accountNumber)
.then(() => {
window.open(url, '_blank');
setTimeout(() => location.reload(), 500);
})
.catch(console.error);
}
</script>
</head>
<body>
<div class="container">
<header>
<img src="https://share.claude.asia/img/logo.png" height="30" alt="logo">
</header>
<main>
<h2 style="text-align:center;">免费账号</h2>
<div class="accounts">
${loginUrls.map((url, i) => `
<a href="${url}"
class="account ${accountStatuses[i].color}"
onclick="updateStatus(${i + 1}, event)">
账号${i + 1}
<span>(${accountStatuses[i].status})</span>
</a>
`).join('')}
</div>
</main>
<footer>
<div class="copyright">© Claude.asia</div>
</footer>
</div>
</body>
</html>`;
}
export default {
async fetch(request, env) {
const url = new URL(request.url);
// Handle click updates
if (url.searchParams.has('clicked')) {
const clickedAccount = parseInt(url.searchParams.get('clicked'));
if (clickedAccount > 0 && clickedAccount <= SESSION_KEYS.length) {
await updateClickTime(clickedAccount, env);
}
return new Response('OK');
}
// Get login URLs from cache or API
const cacheKey = 'login_urls_cache';
let loginUrls;
try {
const cachedData = await env.CLAUDE_KV.get(cacheKey, 'json');
if (cachedData && (Date.now() - cachedData.timestamp) < (CACHE_DURATION * 1000)) {
loginUrls = cachedData.urls;
} else {
// Dynamically generate login URLs based on SESSION_KEYS length
loginUrls = await Promise.all(SESSION_KEYS.map(key => getLoginUrl(key)));
await env.CLAUDE_KV.put(cacheKey, JSON.stringify({
timestamp: Date.now(),
urls: loginUrls
}));
}
} catch (error) {
console.error("Cache Error:", error);
loginUrls = await Promise.all(SESSION_KEYS.map(key => getLoginUrl(key)));
}
// Get account statuses dynamically based on SESSION_KEYS length
const accountStatuses = await Promise.all(
SESSION_KEYS.map((_, i) => getAccountStatus(i + 1, env))
);
// Generate and return HTML
const html = await generateHTML(loginUrls, accountStatuses);
return new Response(html, {
headers: {
'Content-Type': 'text/html;charset=UTF-8'
}
});
}
};
// Configuration
const CACHE_DURATION_MINUTES = 50;//对话缓存时间 min
const CHECK_PERIOD_MINUTES = 240; //繁忙复位时间 min
const RETENTION_PERIOD_MINUTES = 240;
const BASE_URL = 'https://claude.asia';
const AUTH_ENDPOINT = '/manage-api/auth/oauth_token';
const CACHE_KEY = 'login_urls_cache';
// Convert minutes to milliseconds
const CACHE_DURATION_MS = CACHE_DURATION_MINUTES * 60 * 1000;
const CHECK_PERIOD_MS = CHECK_PERIOD_MINUTES * 60 * 1000;
const RETENTION_PERIOD_MS = RETENTION_PERIOD_MINUTES * 60 * 1000;
// Status constants
const STATUS = {
BUSY: { color: 'busy', status: '繁忙' },
FREE: { color: 'free', status: '空闲' }
};
//放SESSION_KEYS的地方,带引号,一行一个
const SESSION_KEYS = [
// [email protected]
'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',
// [email protected] (新加坡三网)
'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',
// [email protected] (日本ijj)
'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',
// 共享的 keys
'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',
'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',
'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'
];
async function getLoginUrl(sessionKey) {
try {
const response = await fetch(`${BASE_URL}${AUTH_ENDPOINT}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
session_key: sessionKey,
unique_name: Date.now().toString()
}),
});
const data = await response.json();
if (data.login_url) {
return data.login_url.startsWith('http')
? data.login_url
: `${BASE_URL}${data.login_url}`;
}
} catch (error) {
console.error("Login URL Error:", error);
}
return '#';
}
async function getAccountStatus(accountNumber, env) {
const key = `clicks_${accountNumber}`;
const currentTime = Date.now();
try {
const clicks = await env.CLAUDE_KV.get(key, 'json') || [];
const recentClicks = clicks.filter(time => (currentTime - time) < CHECK_PERIOD_MS);
return recentClicks.length >= 1 ? STATUS.BUSY : STATUS.FREE;
} catch (error) {
console.error("Status Error:", error);
return STATUS.FREE;
}
}
async function updateClickTime(accountNumber, env) {
const key = `clicks_${accountNumber}`;
const currentTime = Date.now();
try {
const clicks = await env.CLAUDE_KV.get(key, 'json') || [];
const recentClicks = clicks.filter(time => (currentTime - time) < RETENTION_PERIOD_MS);
recentClicks.push(currentTime);
await env.CLAUDE_KV.put(key, JSON.stringify(recentClicks));
} catch (error) {
console.error("Update Click Error:", error);
}
}
async function generateHTML(loginUrls, accountStatuses) {
return `<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>远大港湾</title>
<style>
body, html {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
margin: 0;
padding: 0;
min-height: 100vh;
background: linear-gradient(135deg, #ffffff, #f0f0f0);
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 0;
}
h1, h2 {
color: #2c3e50;
margin: 0;
}
.accounts {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
gap: 15px;
margin: 30px 0;
}
.account {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 80px;
text-decoration: none;
padding: 12px 8px;
border-radius: 12px;
font-size: 0.95rem;
transition: all 0.3s ease;
border: 1px solid rgba(0,0,0,0.1);
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.account.free {
background-color: #81c784;
color: #1b5e20;
}
.account.busy {
background-color: #ef9a9a;
color: #c62828;
}
.account:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.account span {
margin-top: 5px;
font-size: 0.85rem;
opacity: 0.9;
}
footer {
margin-top: 40px;
padding-top: 20px;
border-top: 1px solid #eee;
text-align: center;
color: #666;
}
@media (max-width: 768px) {
.accounts {
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.account {
min-height: 70px;
padding: 10px 5px;
}
}
</style>
<script>
function updateStatus(accountNumber, event) {
event.preventDefault();
const link = event.currentTarget;
const url = link.href;
fetch('?clicked=' + accountNumber)
.then(() => {
window.open(url, '_blank');
setTimeout(() => location.reload(), 500);
})
.catch(console.error);
}
</script>
</head>
<body>
<div class="container">
<header>
<img src="https://share.claude.asia/img/logo.png" height="30" alt="logo">
</header>
<main>
<h2 style="text-align:center;">免费账号</h2>
<div class="accounts">
${loginUrls.map((url, i) => `
<a href="${url}"
class="account ${accountStatuses[i].color}"
onclick="updateStatus(${i + 1}, event)">
账号${i + 1}
<span>(${accountStatuses[i].status})</span>
</a>
`).join('')}
</div>
</main>
<footer>
<div class="copyright">© Claude.asia</div>
</footer>
</div>
</body>
</html>`;
}
export default {
async fetch(request, env) {
const url = new URL(request.url);
// Handle click updates
if (url.searchParams.has('clicked')) {
const clickedAccount = parseInt(url.searchParams.get('clicked'));
if (clickedAccount > 0 && clickedAccount <= SESSION_KEYS.length) {
await updateClickTime(clickedAccount, env);
}
return new Response('OK');
}
// Get login URLs from cache or API
const cacheKey = 'login_urls_cache';
let loginUrls;
try {
const cachedData = await env.CLAUDE_KV.get(cacheKey, 'json');
if (cachedData && (Date.now() - cachedData.timestamp) < (CACHE_DURATION * 1000)) {
loginUrls = cachedData.urls;
} else {
// Dynamically generate login URLs based on SESSION_KEYS length
loginUrls = await Promise.all(SESSION_KEYS.map(key => getLoginUrl(key)));
await env.CLAUDE_KV.put(cacheKey, JSON.stringify({
timestamp: Date.now(),
urls: loginUrls
}));
}
} catch (error) {
console.error("Cache Error:", error);
loginUrls = await Promise.all(SESSION_KEYS.map(key => getLoginUrl(key)));
}
// Get account statuses dynamically based on SESSION_KEYS length
const accountStatuses = await Promise.all(
SESSION_KEYS.map((_, i) => getAccountStatus(i + 1, env))
);
// Generate and return HTML
const html = await generateHTML(loginUrls, accountStatuses);
return new Response(html, {
headers: {
'Content-Type': 'text/html;charset=UTF-8'
}
});
}
};
咳咳 under attack是啥,意思是我下面的这些有些不需要开启是吗?
具体是哪些不需要开启
佬 你这个规则选的是啥,我看你可以添加好多路径
我是下面这个
等下,我试下serv00的看看有没你这问题
既然这么详细,建议整理成新人笔记,把爱传递下去
我试了下serv00的没有长文本问题啊,你后面改了什么设置?
Under Attack
开了后全站都会质询,没有必要
如果开盾了规则这里这样写更好
我默认啥也没改啊
我部署了好几个佬友的new-api和one-api服务
如图所示,部署了6个,用了3个域名,都是长本文有问题
试了下没遇到你说的问题
佬 你这个under attack在哪关的
我想问下下面这些应该没啥问题吧