【既然选择优雅就优雅到底】GPT4私人拼车神器【UI版】

那就没得问题啊


1 个赞

不知道哪里的问题了 照着我的设置搞吧

我把KV在前面定义看看

1 个赞

kv里的at必须设置为空或者取到的accesstoken

老哥解决了没,我刚刚试了一下,发现和你这一样的问题,进入之后一样会出现error :melting_face:


按我上面那些设置好没有问题的

谢谢作者,问题就在这儿,但是不知道为什么 :scream:

常规话题软件开发

我也是进入后有问题

上面都是正常的 按我说的设置就好了

忽略就行

1 个赞

可以试试我的,改进了一点密码错误处理机制,支持2个账号设置(可自行添加)。:

addEventListener("fetch", (event) => {
    event.respondWith(handleRequest(event.request));
});
function parseJwt(token) {
    const base64Url = token.split(".")[1]; // 获取载荷部分
    const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/"); // 将 Base64Url 转为 Base64
    const jsonPayload = decodeURIComponent(
        atob(base64)
            .split("")
            .map(function (c) {
                return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
            })
            .join("")
    );

    return JSON.parse(jsonPayload); // 返回载荷解析后的 JSON 对象
}

async function getOAuthLink(shareToken, YOUR_DOMAIN) {
    const url = `https://${YOUR_DOMAIN}/api/auth/oauth_token`;
    const response = await fetch(url, {
        method: 'POST',
        headers: {
            'Origin': `https://${YOUR_DOMAIN}`,
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            share_token: shareToken
        })
    })
    const data = await response.json();
    return data.login_url;
}

function isTokenExpired(token) {
    const payload = parseJwt(token);
    const currentTime = Math.floor(Date.now() / 1000); // 获取当前时间戳(秒)
    return payload.exp < currentTime; // 检查 token 是否过期
}

async function handleRequest(request) {
    const requestURL = new URL(request.url);
    const path = requestURL.pathname;

      // 检查路径是否匹配 "/auth/login_auth0"
      if (path !== "/auth/login_auth0") {
        requestURL.host = "new.oaifree.com";
        return fetch(new Request(requestURL, request));
    }

    
 // 这里填入你的 JWT

    // 如果 Token 未过期,继续执行原来的逻辑
    if (request.method === "POST") {
        const formData = await request.formData();
        const accountChoice = formData.get("account_choice");

        // 根据选择获取对应的 access_token
        // @ts-ignore
        const token = accountChoice === '1' ? await oai_global_variables.get("at1") : await oai_global_variables.get("at2");
        // @ts-ignore
        const SITE_PASSWORD =
            // @ts-ignore
            (await oai_global_variables.get("SITE_PASSWORD")) || "";
        const site_password = formData.get("site_password") || "";
        if (site_password !== SITE_PASSWORD) {
            const uniqueName = formData.get("unique_name") || ""; // 获取表单中的昵称值
            const accountChoice = formData.get("account_choice") || "1"; // 获取表单中的账号选择,缺省值为"1"
            const htmlContent = `
            <!DOCTYPE html>
            <html lang="en">
            
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <style>
                .input-wrapper select {
                    width: 320px; /* 和其他 input 元素保持一致 */
                    height: 52px; /* 调整高度以匹配设计 */
                    padding: 10px; /* 适当的内边距以美化视觉效果 */
                    border-radius: 5px; /* 圆角与输入框保持一致 */
                    border: 1px solid #ccc; /* 初始边框颜色 */
                    background-color: #ffffff; /* 背景色 */
                    font-size: 16px; /* 字体大小与其他输入框一致 */
                    color: red; /* 字体颜色,以提高可读性 */
                    outline: none; /* 去除默认轮廓 */
                    -webkit-appearance: none; /* 删除iOS默认样式 */
                    -moz-appearance: none; /* 删除Firefox默认样式 */
                    appearance: none; /* 删除默认样式 */
                }
                
                .input-wrapper select:focus {
                    border-color: #0f9977; /* 聚焦时的边框颜色 */
                }
                
                .input-wrapper select:hover {
                    border-color: #0f9977; /* 悬停时的边框颜色 */
                }
                
                .input-wrapper label {
                    position: absolute;
                    left: 10px;
                    top: -10px; /* 调整标签位置,使其在动画开始时就位 */
                    transition: top 0.3s, font-size 0.3s, color 0.3s;
                    color: #ccc;
                    background-color: #ffffff;
                    padding: 0 5px; /* 标签的内边距防止背景与边框重叠 */
                }
                
                .input-wrapper select:not(:placeholder-shown) + label,
                .input-wrapper select:focus + label {
                    top: -20px; /* 向上移动标签 */
                    font-size: 12px; /* 缩小字体 */
                    color: #0f9977; /* 改变颜色 */
                }
                
                    .title {
                        font-size: 32px;
                        font: "Söhne";
                        color: #2d333a;
                        width: 320px;
                        text-align: center;
                    }
                    .oai-header {
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        width: 100%;
                        background-color: #fff;
                    }
                    header {
                        unicode-bidi: isolate;
                    }
                    body {
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        height: 90vh;
                        overflow: hidden;
                    }
                    h1{
                        text-align: center;
                    }
                    input{
                            appearance: none;
                            -webkit-appearance: none;
                            -moz-appearance: none;
                            outline: none;
                        }
                    .input-wrapper {
                        position: relative;
                        margin-bottom: 20px;
                    }
            
                    .input-wrapper label {
                        position: absolute;
                        left: 10px;
                        top: 14px;
                        transition: 0.3s;
                        color: #ccc;
                        background-color: #ffffff;
                    }
            
                    .input-wrapper input {
                        width: 298.4px;
                        height: 50.4px;
                        padding: 0 10px;
                        border-radius: 5px;
                        border: 1px solid #ccc;
                        display: block;
                        font-size: 16px;
                    }
                    .input-wrapper input:not(:placeholder-shown) {
                        border-color: #0f9977 !important;
                    }
                    .input-wrapper input:focus {
                        border-color: #0f9977 !important;
                    }
            
                    .input-wrapper input:focus + label,
                    .input-wrapper input:not(:placeholder-shown) + label {
                        top: -10px;
                        left: 10px;
                        font-size: 16px;
                        color: #0f9977;
                    }
            
                    button {
                        background-color: #0f9977;
                        color: #ffffff;
                        padding: 10px 20px;
                        border: none;
                        border-radius: 5px;
                        cursor: pointer;
                        font-size: 16px;
                        font-weight: 600;
                        width: 320px !important;
                        height: 52px;
                    }
            
                    @media (max-width: 768px) {
                        body,
                        form,
                        .response-container {
                            padding: 20px;
                        }
                    }
                </style>
            </head>
            
            <body>
                <div>
                <header class="oai-header" data-immersive-translate-walked="a50a507b-b686-4aff-b614-6c58864d5cec"><img src="https://img2.imgtp.com/2024/04/20/z9twuEmo.svg" alt="OpenAI's Logo"></header>
                     <h1 class="title" data-immersive-translate-walked="a50a507b-b686-4aff-b614-6c58864d5cec">欢迎回来</h1>
                    <form method="POST">
                    <div class="input-wrapper">
                    <select id="account_choice" name="account_choice" required>
                        <option value="1" ${accountChoice === '1' ? 'selected' : ''}>ChatGPT Team账号1</option>
                        <option value="2" ${accountChoice === '2' ? 'selected' : ''}>ChatGPT Team账号2</option>
                    </select>
                </div>
                    <div class="input-wrapper">
                      <input type="text" id="unique_name" name="unique_name" placeholder=" " required value="${uniqueName}">
                      <label for="unique_name">请输入一个独一无二的昵称</label>
                    </div>
                    <div class="input-wrapper">
                      <input type="password" id="site_password" name="site_password" placeholder=" " required>
                      <label for="site_password">请输入正确的访问密码</label>
                      <span id="error-message" style="color: red; display: none;">访问密码错误</span>
                    </div>
                    <button type="submit">继续</button>
                  </form>
                  <script>
                    document.getElementById('error-message').style.display = 'inline'; // 显示错误消息
                    setTimeout(() => {
                      document.getElementById('error-message').style.display = 'none'; // 2秒后隐藏错误消息
                    }, 2000);
                    document.getElementById('site_password').focus(); // 自动聚焦到密码输入框
                     document.addEventListener('DOMContentLoaded', function () {
                        var selectElement = document.getElementById('account_choice');
                        var labelElement = document.querySelector('label[for="account_choice"]');

                    selectElement.addEventListener('change', function() {
                        var selectedOption = selectElement.options[selectElement.selectedIndex].text;
                        labelElement.textContent = selectedOption; // 更新标签文本为选中的选项
                    });
    });
 
                  </script>
                </body>
                </html>
                `;
                
                    return new Response(htmlContent, {
                        status: 401,
                        headers: { "Content-Type": "text/html" },
                    });
                }
                if (isTokenExpired(token)) {
                    // 如果 Token 过期,执行获取新 Token 的逻辑
                    const url = "https://token.oaifree.com/api/auth/refresh";
                    // @ts-ignore
                    const refreshToken = await oai_global_variables.get("rt"); // 实际情况下你可能会从某处获取这个值
            
                    // 发送 POST 请求
                    const response = await fetch(url, {
                        method: "POST",
                        headers: {
                            "Content-Type":
                                "application/x-www-form-urlencoded;charset=UTF-8",
                        },
                        body: `refresh_token=${refreshToken}`,
                    });
            
                    // 检查响应状态
                    if (response.ok) {
                        const data = await response.json();
                        const token = data.access_token;
                        // @ts-ignore
                        await oai_global_variables.put(accountChoice === '1' ? "at1" : "at2", token);
            
            
                    } else {
                        return new Response("Error fetching access token", {
                            status: response.status,
                        });
                    }
                }
        // @ts-ignore
        const access_token = token;
        const unique_name = formData.get("unique_name");
        const site_limit = "";
        const expires_in = "0";
        const gpt35_limit = "-1";
        const gpt4_limit = "-1";
        const show_conversations = "false";
        const reset_limit = "false";

        const url = "https://chat.oaifree.com/token/register";
        const body = new URLSearchParams({
            unique_name,
            access_token, // 使用来自表单或KV变量的 access_token
            site_limit,
            expires_in,
            gpt35_limit,
            gpt4_limit,
            show_conversations,
            reset_limit,
        }).toString();

        const apiResponse = await fetch(url, {
            method: "POST",
            headers: {
                "Content-Type": "application/x-www-form-urlencoded",
            },
            body: body,
        });

        const respJson = await apiResponse.json();
        const tokenKey =
            "token_key" in respJson ? respJson.token_key : "未找到 Share_token";

        // @ts-ignore
      const YOUR_DOMAIN = await oai_global_variables.get('YOUR_DOMAIN') || requestURL.host;
  
      return Response.redirect(`https://${YOUR_DOMAIN}/auth/login_share?token=${tokenKey}`, 301)
    }else {
        const formHtml = `
        <!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
    .input-wrapper select {
        width: 320px; /* 和其他 input 元素保持一致 */
        height: 52px; /* 调整高度以匹配设计 */
        padding: 10px; /* 适当的内边距以美化视觉效果 */
        border-radius: 5px; /* 圆角与输入框保持一致 */
        border: 1px solid #ccc; /* 初始边框颜色 */
        background-color: #ffffff; /* 背景色 */
        font-size: 16px; /* 字体大小与其他输入框一致 */
        color: red; /* 字体颜色,以提高可读性 */
        outline: none; /* 去除默认轮廓 */
        -webkit-appearance: none; /* 删除iOS默认样式 */
        -moz-appearance: none; /* 删除Firefox默认样式 */
        appearance: none; /* 删除默认样式 */
    }
    
    .input-wrapper select:focus {
        border-color: #0f9977; /* 聚焦时的边框颜色 */
    }
    
    .input-wrapper select:hover {
        border-color: #0f9977; /* 悬停时的边框颜色 */
    }
    
    .input-wrapper label {
        position: absolute;
        left: 10px;
        top: -10px; /* 调整标签位置,使其在动画开始时就位 */
        transition: top 0.3s, font-size 0.3s, color 0.3s;
        color: #ccc;
        background-color: #ffffff;
        padding: 0 5px; /* 标签的内边距防止背景与边框重叠 */
    }
    
    .input-wrapper select:not(:placeholder-shown) + label,
    .input-wrapper select:focus + label {
        top: -20px; /* 向上移动标签 */
        font-size: 12px; /* 缩小字体 */
        color: #0f9977; /* 改变颜色 */
    }
    
        .title {
            font-size: 32px;
            font: "Söhne";
            color: #2d333a;
            width: 320px;
            text-align: center;
        }
        .oai-header {
            display: flex;
            justify-content: center;
            align-items: center;
            width: 100%;
            background-color: #fff;
        }
        header {
            unicode-bidi: isolate;
        }
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 90vh;
            overflow: hidden;
        }
        h1{
            text-align: center;
        }
        input{
                appearance: none;
                -webkit-appearance: none;
                -moz-appearance: none;
                outline: none;
            }
        .input-wrapper {
            position: relative;
            margin-bottom: 20px;
        }

        .input-wrapper label {
            position: absolute;
            left: 10px;
            top: 14px;
            transition: 0.3s;
            color: #ccc;
            background-color: #ffffff;
        }

        .input-wrapper input {
            width: 298.4px;
            height: 50.4px;
            padding: 0 10px;
            border-radius: 5px;
            border: 1px solid #ccc;
            display: block;
            font-size: 16px;
        }
        .input-wrapper input:not(:placeholder-shown) {
            border-color: #0f9977 !important;
        }
        .input-wrapper input:focus {
            border-color: #0f9977 !important;
        }

        .input-wrapper input:focus + label,
        .input-wrapper input:not(:placeholder-shown) + label {
            top: -10px;
            left: 10px;
            font-size: 16px;
            color: #0f9977;
        }

        button {
            background-color: #0f9977;
            color: #ffffff;
            padding: 10px 20px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 16px;
            font-weight: 600;
            width: 320px !important;
            height: 52px;
        }

        @media (max-width: 768px) {
            body,
            form,
            .response-container {
                padding: 20px;
            }
        }
    </style>
</head>
<body>
    <div>
    <header class="oai-header" data-immersive-translate-walked="a50a507b-b686-4aff-b614-6c58864d5cec"><img src="https://img2.imgtp.com/2024/04/20/z9twuEmo.svg" alt="OpenAI's Logo"></header>
    <h1 class="title" data-immersive-translate-walked="a50a507b-b686-4aff-b614-6c58864d5cec">欢迎回来</h1>
        <form method="POST">
        <div class="input-wrapper">
        <select id="account_choice" name="account_choice" required>
            <option value="1">ChatGPT Team账号1</option>
            <option value="2">ChatGPT Team账号2</option>
        </select>
    </div>
            <div class="input-wrapper">
                <input type="text" id="unique_name" name="unique_name" placeholder=" " required value="">
                <label for="unique_name">请输入一个独一无二的昵称</label>
            </div>
            <div class="input-wrapper">
                <input type="password" id="site_password" name="site_password" placeholder=" ">
                <label for="site_password">请输入正确的访问密码</label>
            </div>
            <button type="submit">继续</button>
        </form>
        <script>
        document.addEventListener('DOMContentLoaded', function () {
            var selectElement = document.getElementById('account_choice');
            var labelElement = document.querySelector('label[for="account_choice"]');
    
            selectElement.addEventListener('change', function() {
                var selectedOption = selectElement.options[selectElement.selectedIndex].text;
                labelElement.textContent = selectedOption; // 更新标签文本为选中的选项
            });
        });
     
                      </script>
    </div>
</body>

</html>
    `;

        return new Response(formHtml, {
            headers: {
                "Content-Type": "text/html; charset=utf-8",
            },
        });
    }
}


YOUR_DOMAIN可以填自己的域名在这里设置

这里链接kv数据库

效果如图:

2 个赞

不错 赞

:hand_with_index_finger_and_thumb_crossed:,感谢,新玩意儿也不错 :hand_with_index_finger_and_thumb_crossed: :hugs:

作者你好,我想问个问题,我也不太懂,摸索了会儿。就是说我KV要绑定自己的反代,填完弄好了之后点击continue会跳转到pandora,代码部分都是复制您的,这是啥啥问题呐

:+1: :+1: :+1:

kv怎么设置的

1 个赞

浏览上面的之后,我kv设置的是和他们一样的,就是your。domain设置成了自己的,也绑定了,代码里面我不大懂,也没敢改。(额,就是那个是反代,我看了好多之后,填入的是已经反代好的new.oaifree.com

原本自己的域名不用反代了 代码里有反代操作

1 个赞

:innocent: :innocent: