dsh-plugin-image-workbench 1.1.5 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.en.md +5 -3
- package/README.md +7 -3
- package/client.js +241 -241
- package/cordis.patch.yml +14 -14
- package/host.js +51 -0
- package/install.mjs +333 -387
- package/package.json +3 -2
- package/scripts/fetch-style-images.mjs +104 -0
- package/scripts/vendor-snapshot.py +154 -154
- package/server/access.py +26 -26
- package/server/app.py +1329 -1329
- package/server/catalog.py +147 -147
- package/server/composer.py +391 -391
- package/server/drafts.py +158 -158
- package/server/history.py +575 -575
- package/server/imaging.py +172 -172
- package/server/pool.py +1335 -1335
- package/server/pool_admin.py +921 -921
- package/server/pool_service.py +1073 -1073
- package/server/requirements.txt +6 -6
- package/server/smoke_check.py +402 -402
- package/server/static/access.html +202 -202
- package/vendor/chatgpt2api/source/.env.example +82 -82
- package/vendor/chatgpt2api/source/.python-version +1 -1
- package/vendor/chatgpt2api/source/LICENSE +21 -21
- package/vendor/chatgpt2api/source/README.md +391 -391
- package/vendor/chatgpt2api/source/VERSION +1 -1
- package/vendor/chatgpt2api/source/api/__init__.py +2 -2
- package/vendor/chatgpt2api/source/api/accounts.py +537 -537
- package/vendor/chatgpt2api/source/api/ai.py +217 -217
- package/vendor/chatgpt2api/source/api/app.py +62 -62
- package/vendor/chatgpt2api/source/api/errors.py +46 -46
- package/vendor/chatgpt2api/source/api/image_inputs.py +309 -309
- package/vendor/chatgpt2api/source/api/image_tasks.py +120 -120
- package/vendor/chatgpt2api/source/api/support.py +134 -134
- package/vendor/chatgpt2api/source/api/system.py +365 -365
- package/vendor/chatgpt2api/source/assets/kunrouai.svg +50 -50
- package/vendor/chatgpt2api/source/config.default.json +108 -108
- package/vendor/chatgpt2api/source/main.py +9 -9
- package/vendor/chatgpt2api/source/pyproject.toml +27 -27
- package/vendor/chatgpt2api/source/scripts/init_proxy_config.py +186 -186
- package/vendor/chatgpt2api/source/scripts/migrate_storage.py +163 -163
- package/vendor/chatgpt2api/source/scripts/privoxy-warp.conf +13 -13
- package/vendor/chatgpt2api/source/scripts/test_outlook_token_mailbox.py +385 -385
- package/vendor/chatgpt2api/source/scripts/test_storage.py +129 -129
- package/vendor/chatgpt2api/source/scripts/verify_oauth_refresh.py +92 -92
- package/vendor/chatgpt2api/source/services/account_service.py +1757 -1757
- package/vendor/chatgpt2api/source/services/auth_service.py +253 -253
- package/vendor/chatgpt2api/source/services/backup_service.py +671 -671
- package/vendor/chatgpt2api/source/services/config.py +667 -667
- package/vendor/chatgpt2api/source/services/content_filter.py +242 -242
- package/vendor/chatgpt2api/source/services/cpa_service.py +315 -315
- package/vendor/chatgpt2api/source/services/editable_file_task_service.py +260 -260
- package/vendor/chatgpt2api/source/services/image_service.py +376 -376
- package/vendor/chatgpt2api/source/services/image_storage_service.py +405 -405
- package/vendor/chatgpt2api/source/services/image_tags_service.py +76 -76
- package/vendor/chatgpt2api/source/services/image_task_service.py +550 -550
- package/vendor/chatgpt2api/source/services/log_service.py +337 -337
- package/vendor/chatgpt2api/source/services/model_service.py +182 -182
- package/vendor/chatgpt2api/source/services/oauth_login_service.py +267 -267
- package/vendor/chatgpt2api/source/services/openai_backend_api.py +2763 -2763
- package/vendor/chatgpt2api/source/services/openai_oauth.py +32 -32
- package/vendor/chatgpt2api/source/services/protocol/__init__.py +2 -2
- package/vendor/chatgpt2api/source/services/protocol/anthropic_v1_messages.py +307 -307
- package/vendor/chatgpt2api/source/services/protocol/chat_completion_cache.py +238 -238
- package/vendor/chatgpt2api/source/services/protocol/conversation.py +1644 -1644
- package/vendor/chatgpt2api/source/services/protocol/error_response.py +124 -124
- package/vendor/chatgpt2api/source/services/protocol/openai_search.py +19 -19
- package/vendor/chatgpt2api/source/services/protocol/openai_v1_chat_complete.py +316 -316
- package/vendor/chatgpt2api/source/services/protocol/openai_v1_image_edit.py +86 -86
- package/vendor/chatgpt2api/source/services/protocol/openai_v1_image_generations.py +42 -42
- package/vendor/chatgpt2api/source/services/protocol/openai_v1_models.py +53 -53
- package/vendor/chatgpt2api/source/services/protocol/openai_v1_response.py +453 -453
- package/vendor/chatgpt2api/source/services/protocol/web_search_tool.py +160 -160
- package/vendor/chatgpt2api/source/services/proxy_service.py +648 -648
- package/vendor/chatgpt2api/source/services/storage/__init__.py +5 -5
- package/vendor/chatgpt2api/source/services/storage/base.py +38 -38
- package/vendor/chatgpt2api/source/services/storage/database_storage.py +194 -194
- package/vendor/chatgpt2api/source/services/storage/factory.py +104 -104
- package/vendor/chatgpt2api/source/services/storage/git_storage.py +183 -183
- package/vendor/chatgpt2api/source/services/storage/json_storage.py +95 -95
- package/vendor/chatgpt2api/source/services/sub2api_service.py +531 -531
- package/vendor/chatgpt2api/source/utils/helper.py +469 -469
- package/vendor/chatgpt2api/source/utils/image_tokens.py +346 -346
- package/vendor/chatgpt2api/source/utils/log.py +110 -110
- package/vendor/chatgpt2api/source/utils/pkce.py +19 -19
- package/vendor/chatgpt2api/source/utils/pow.py +207 -207
- package/vendor/chatgpt2api/source/utils/sentinel.py +159 -159
- package/vendor/chatgpt2api/source/utils/turnstile.py +184 -184
- package/vendor/chatgpt2api/source/uv.lock +904 -904
- package/vendor/chatgpt2api/source/web/bun.lock +1501 -1501
- package/vendor/chatgpt2api/source/web/components.json +24 -24
- package/vendor/chatgpt2api/source/web/eslint.config.mjs +17 -17
- package/vendor/chatgpt2api/source/web/next.config.ts +40 -40
- package/vendor/chatgpt2api/source/web/package.json +58 -58
- package/vendor/chatgpt2api/source/web/postcss.config.mjs +5 -5
- package/vendor/chatgpt2api/source/web/src/app/accounts/components/account-import-dialog.tsx +925 -925
- package/vendor/chatgpt2api/source/web/src/app/accounts/page.tsx +1307 -1307
- package/vendor/chatgpt2api/source/web/src/app/debug/components/chat-panel.tsx +224 -224
- package/vendor/chatgpt2api/source/web/src/app/debug/components/editable-file-panel.tsx +444 -444
- package/vendor/chatgpt2api/source/web/src/app/debug/components/ppt-panel.tsx +9 -9
- package/vendor/chatgpt2api/source/web/src/app/debug/components/psd-panel.tsx +9 -9
- package/vendor/chatgpt2api/source/web/src/app/debug/components/search-panel.tsx +172 -172
- package/vendor/chatgpt2api/source/web/src/app/debug/components/skill-panel.tsx +169 -169
- package/vendor/chatgpt2api/source/web/src/app/debug/components/types.ts +39 -39
- package/vendor/chatgpt2api/source/web/src/app/debug/page.tsx +59 -59
- package/vendor/chatgpt2api/source/web/src/app/globals.css +230 -230
- package/vendor/chatgpt2api/source/web/src/app/image/components/image-composer.tsx +542 -542
- package/vendor/chatgpt2api/source/web/src/app/image/components/image-results.tsx +554 -554
- package/vendor/chatgpt2api/source/web/src/app/image/components/image-sidebar.tsx +176 -176
- package/vendor/chatgpt2api/source/web/src/app/image/page.tsx +1799 -1799
- package/vendor/chatgpt2api/source/web/src/app/image-manager/page.tsx +732 -732
- package/vendor/chatgpt2api/source/web/src/app/layout.tsx +50 -50
- package/vendor/chatgpt2api/source/web/src/app/login/page.tsx +101 -101
- package/vendor/chatgpt2api/source/web/src/app/logs/page.tsx +356 -356
- package/vendor/chatgpt2api/source/web/src/app/page.tsx +30 -30
- package/vendor/chatgpt2api/source/web/src/app/settings/components/api-docs-card.tsx +341 -341
- package/vendor/chatgpt2api/source/web/src/app/settings/components/backup-settings-card.tsx +447 -447
- package/vendor/chatgpt2api/source/web/src/app/settings/components/base-url-card.tsx +71 -71
- package/vendor/chatgpt2api/source/web/src/app/settings/components/config-card.tsx +491 -491
- package/vendor/chatgpt2api/source/web/src/app/settings/components/cpa-pool-dialog.tsx +108 -108
- package/vendor/chatgpt2api/source/web/src/app/settings/components/cpa-pools-card.tsx +169 -169
- package/vendor/chatgpt2api/source/web/src/app/settings/components/import-browser-dialog.tsx +185 -185
- package/vendor/chatgpt2api/source/web/src/app/settings/components/proxy-runtime-card.tsx +379 -379
- package/vendor/chatgpt2api/source/web/src/app/settings/components/proxy-settings-card.tsx +127 -127
- package/vendor/chatgpt2api/source/web/src/app/settings/components/proxy-settings.tsx +200 -200
- package/vendor/chatgpt2api/source/web/src/app/settings/components/settings-header.tsx +12 -12
- package/vendor/chatgpt2api/source/web/src/app/settings/components/sub2api-connections.tsx +886 -886
- package/vendor/chatgpt2api/source/web/src/app/settings/components/third-party-apps-card.tsx +81 -81
- package/vendor/chatgpt2api/source/web/src/app/settings/components/user-keys-card.tsx +422 -422
- package/vendor/chatgpt2api/source/web/src/app/settings/page.tsx +135 -135
- package/vendor/chatgpt2api/source/web/src/app/settings/store.ts +1069 -1069
- package/vendor/chatgpt2api/source/web/src/components/date-range-filter.tsx +49 -49
- package/vendor/chatgpt2api/source/web/src/components/header-actions.tsx +24 -24
- package/vendor/chatgpt2api/source/web/src/components/image-lightbox.tsx +434 -434
- package/vendor/chatgpt2api/source/web/src/components/image-thumbnail.tsx +46 -46
- package/vendor/chatgpt2api/source/web/src/components/theme-script.tsx +18 -18
- package/vendor/chatgpt2api/source/web/src/components/theme-toggle.tsx +14 -14
- package/vendor/chatgpt2api/source/web/src/components/top-nav.tsx +263 -263
- package/vendor/chatgpt2api/source/web/src/components/ui/animated-theme-toggler.tsx +256 -256
- package/vendor/chatgpt2api/source/web/src/components/ui/badge.tsx +41 -41
- package/vendor/chatgpt2api/source/web/src/components/ui/button.tsx +59 -59
- package/vendor/chatgpt2api/source/web/src/components/ui/calendar.tsx +46 -46
- package/vendor/chatgpt2api/source/web/src/components/ui/card.tsx +61 -61
- package/vendor/chatgpt2api/source/web/src/components/ui/checkbox.tsx +27 -27
- package/vendor/chatgpt2api/source/web/src/components/ui/dia-text-reveal.tsx +267 -267
- package/vendor/chatgpt2api/source/web/src/components/ui/dialog.tsx +132 -132
- package/vendor/chatgpt2api/source/web/src/components/ui/field.tsx +13 -13
- package/vendor/chatgpt2api/source/web/src/components/ui/input.tsx +19 -19
- package/vendor/chatgpt2api/source/web/src/components/ui/label.tsx +24 -24
- package/vendor/chatgpt2api/source/web/src/components/ui/morphing-text.tsx +149 -149
- package/vendor/chatgpt2api/source/web/src/components/ui/popover.tsx +38 -38
- package/vendor/chatgpt2api/source/web/src/components/ui/select.tsx +175 -175
- package/vendor/chatgpt2api/source/web/src/components/ui/sheet.tsx +143 -143
- package/vendor/chatgpt2api/source/web/src/components/ui/table.tsx +29 -29
- package/vendor/chatgpt2api/source/web/src/components/ui/tabs.tsx +91 -91
- package/vendor/chatgpt2api/source/web/src/components/ui/text-3d-flip.tsx +269 -269
- package/vendor/chatgpt2api/source/web/src/components/ui/textarea.tsx +18 -18
- package/vendor/chatgpt2api/source/web/src/components/version-release-dialog.tsx +127 -127
- package/vendor/chatgpt2api/source/web/src/constants/common-env.ts +6 -6
- package/vendor/chatgpt2api/source/web/src/hooks/use-version-check.ts +85 -85
- package/vendor/chatgpt2api/source/web/src/lib/api.ts +926 -926
- package/vendor/chatgpt2api/source/web/src/lib/auth-session.ts +26 -26
- package/vendor/chatgpt2api/source/web/src/lib/release.ts +25 -25
- package/vendor/chatgpt2api/source/web/src/lib/request.ts +93 -93
- package/vendor/chatgpt2api/source/web/src/lib/use-auth-guard.ts +89 -89
- package/vendor/chatgpt2api/source/web/src/lib/utils.ts +6 -6
- package/vendor/chatgpt2api/source/web/src/store/auth.ts +112 -112
- package/vendor/chatgpt2api/source/web/src/store/editable-file-history.ts +33 -33
- package/vendor/chatgpt2api/source/web/src/store/image-conversations.ts +318 -318
- package/vendor/chatgpt2api/source/web/tsconfig.json +42 -42
|
@@ -1,202 +1,202 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="zh-CN">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
-
<title>申请访问 · 手绘工坊号池工作台</title>
|
|
7
|
-
<style>
|
|
8
|
-
:root{
|
|
9
|
-
--bg:#f5f3fb; --panel:#ffffff; --ink:#1f1b2e; --ink-2:#5b5573; --ink-3:#8b86a3;
|
|
10
|
-
--line:#e8e4f5; --primary:#6a5ae0; --primary-2:#8b7cf6; --pink:#ff6b9a;
|
|
11
|
-
--ok:#12b886; --err:#e03131; --chip:#f1eefe;
|
|
12
|
-
}
|
|
13
|
-
*{box-sizing:border-box}
|
|
14
|
-
[hidden]{display:none!important}
|
|
15
|
-
body{margin:0;min-height:100vh;color:var(--ink);
|
|
16
|
-
font:14px/1.7 -apple-system,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;
|
|
17
|
-
background:radial-gradient(1100px 620px at 12% -12%,#e6dfff 0%,transparent 62%),
|
|
18
|
-
radial-gradient(900px 560px at 100% 0%,#ffe7f0 0%,transparent 58%),
|
|
19
|
-
var(--bg);
|
|
20
|
-
display:flex;align-items:center;justify-content:center;padding:24px}
|
|
21
|
-
.card{width:100%;max-width:420px;background:var(--panel);border:1px solid var(--line);
|
|
22
|
-
border-radius:20px;box-shadow:0 18px 60px rgba(80,60,160,.13);padding:30px 28px 24px}
|
|
23
|
-
.brand{display:inline-flex;align-items:center;gap:8px;font-size:11px;letter-spacing:.6px;
|
|
24
|
-
color:var(--primary);background:var(--chip);border:1px solid #ddd6fb;border-radius:20px;
|
|
25
|
-
padding:5px 12px;margin-bottom:18px}
|
|
26
|
-
.brand i{width:7px;height:7px;border-radius:50%;background:var(--primary);display:block}
|
|
27
|
-
h1{font-size:22px;margin:0 0 6px;letter-spacing:.5px}
|
|
28
|
-
.lead{font-size:12.5px;color:var(--ink-2);margin:0 0 22px;line-height:1.8}
|
|
29
|
-
.lead b{color:var(--ink);font-weight:600}
|
|
30
|
-
.steps{display:flex;gap:6px;margin:0 0 20px}
|
|
31
|
-
.steps span{flex:1;height:4px;border-radius:4px;background:var(--line)}
|
|
32
|
-
.steps span.on{background:linear-gradient(90deg,var(--primary),var(--pink))}
|
|
33
|
-
label{display:block;font-size:11.5px;color:var(--ink-2);margin:0 0 7px;font-weight:600}
|
|
34
|
-
input{width:100%;border:1px solid var(--line);border-radius:11px;background:#fbfaff;
|
|
35
|
-
padding:12px 13px;font:inherit;color:var(--ink);outline:none;transition:.15s}
|
|
36
|
-
input:focus{border-color:var(--primary-2);background:#fff;box-shadow:0 0 0 3px rgba(139,124,246,.14)}
|
|
37
|
-
input.code{font-size:22px;letter-spacing:9px;text-align:center;font-weight:600;
|
|
38
|
-
font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
|
|
39
|
-
.btn{width:100%;border:0;border-radius:11px;padding:12px 14px;font:inherit;font-weight:600;
|
|
40
|
-
cursor:pointer;margin-top:14px;transition:.15s;background:#f1eefe;color:var(--primary)}
|
|
41
|
-
.btn:hover{filter:brightness(.97)}
|
|
42
|
-
.btn.primary{background:linear-gradient(135deg,var(--primary),var(--pink));color:#fff;
|
|
43
|
-
box-shadow:0 8px 20px rgba(106,90,224,.26)}
|
|
44
|
-
.btn.ghost{background:#fff;border:1px solid var(--line);color:var(--ink-2);font-weight:500}
|
|
45
|
-
.btn:disabled{opacity:.55;cursor:not-allowed}
|
|
46
|
-
.msg{margin-top:14px;font-size:12px;line-height:1.7;border-radius:10px;padding:0;min-height:0}
|
|
47
|
-
.msg:not(:empty){padding:10px 12px;border:1px solid var(--line);background:#faf9ff;color:var(--ink-2)}
|
|
48
|
-
.msg.err{border-color:#ffd6d6;background:#fff5f5;color:#c92a2a}
|
|
49
|
-
.msg.ok{border-color:#c3f0dd;background:#f2fcf8;color:#087f5b}
|
|
50
|
-
.notice{background:#f2fcf8;border:1px solid #c3f0dd;color:#087f5b;border-radius:11px;
|
|
51
|
-
padding:11px 13px;font-size:12px;line-height:1.75;margin:0 0 18px}
|
|
52
|
-
.foot{margin-top:22px;padding-top:16px;border-top:1px solid var(--line);
|
|
53
|
-
display:flex;justify-content:space-between;align-items:center;font-size:11px;color:var(--ink-3)}
|
|
54
|
-
.foot a{color:var(--ink-3);text-decoration:none;cursor:pointer;border-bottom:1px dashed var(--line)}
|
|
55
|
-
.foot a:hover{color:var(--primary)}
|
|
56
|
-
.admin{margin-top:16px;padding:14px;border:1px solid var(--line);border-radius:12px;background:#fbfaff}
|
|
57
|
-
.admin p{margin:0 0 10px;font-size:11.5px;color:var(--ink-2);line-height:1.7}
|
|
58
|
-
.hint{font-size:11px;color:var(--ink-3);margin:12px 0 0;line-height:1.7}
|
|
59
|
-
</style>
|
|
60
|
-
</head>
|
|
61
|
-
<body>
|
|
62
|
-
<div class="card">
|
|
63
|
-
<div class="brand"><i></i>手绘工坊 · 号池工作台</div>
|
|
64
|
-
<h1>申请访问</h1>
|
|
65
|
-
<p class="lead">工作台仅供受邀使用。填写你的邮箱点<b>申请访问</b>,管理员会把验证码回复到这个邮箱。收到后回到本页填入邮箱和验证码即可进入。</p>
|
|
66
|
-
<div class="steps"><span id="s1" class="on"></span><span id="s2"></span></div>
|
|
67
|
-
|
|
68
|
-
<div id="step1">
|
|
69
|
-
<label for="email">申请邮箱</label>
|
|
70
|
-
<input id="email" type="email" maxlength="254" autocomplete="email" spellcheck="false" placeholder="name@example.com">
|
|
71
|
-
<button id="reqBtn" class="btn primary" type="button">申请访问</button>
|
|
72
|
-
<p class="hint">请填能收信的邮箱,管理员会把验证码回复到这里。</p>
|
|
73
|
-
</div>
|
|
74
|
-
|
|
75
|
-
<div id="step2" hidden>
|
|
76
|
-
<div class="notice" id="notice">申请已提交,验证码会回复到你填的邮箱。</div>
|
|
77
|
-
<label for="email2">申请时用的邮箱</label>
|
|
78
|
-
<input id="email2" type="email" maxlength="254" autocomplete="email" spellcheck="false">
|
|
79
|
-
<label for="code" style="margin-top:14px">验证码</label>
|
|
80
|
-
<input id="code" class="code" type="text" inputmode="numeric" autocomplete="one-time-code" placeholder="000000">
|
|
81
|
-
<button id="verBtn" class="btn primary" type="button">进入工作台</button>
|
|
82
|
-
<button id="backBtn" class="btn ghost" type="button">换一个邮箱重新申请</button>
|
|
83
|
-
</div>
|
|
84
|
-
|
|
85
|
-
<div id="msg" class="msg" role="status"></div>
|
|
86
|
-
|
|
87
|
-
<div class="foot">
|
|
88
|
-
<span>验证码 24 小时有效 · 一次性 · 与邮箱绑定</span>
|
|
89
|
-
<a id="adminToggle" type="button">管理员入口</a>
|
|
90
|
-
</div>
|
|
91
|
-
<div id="adminBox" class="admin" hidden>
|
|
92
|
-
<p>管理员可凭主口令直接进入,不需要申请验证码。主口令只保存在服务器上,请勿写进共享文档。</p>
|
|
93
|
-
<label for="master">主口令</label>
|
|
94
|
-
<input id="master" type="password" autocomplete="current-password" placeholder="输入主口令">
|
|
95
|
-
<button id="masterBtn" class="btn" type="button">进入工作台</button>
|
|
96
|
-
</div>
|
|
97
|
-
</div>
|
|
98
|
-
|
|
99
|
-
<script>
|
|
100
|
-
(function(){
|
|
101
|
-
var $ = function(id){ return document.getElementById(id); };
|
|
102
|
-
var msg = $('msg');
|
|
103
|
-
function say(t, cls){
|
|
104
|
-
msg.textContent = t || '';
|
|
105
|
-
msg.className = 'msg' + (cls ? ' ' + cls : '');
|
|
106
|
-
}
|
|
107
|
-
function busy(btn, on){
|
|
108
|
-
if(on){
|
|
109
|
-
if(!btn.dataset.label) btn.dataset.label = btn.textContent;
|
|
110
|
-
btn.disabled = true;
|
|
111
|
-
btn.textContent = '处理中…';
|
|
112
|
-
}else{
|
|
113
|
-
btn.disabled = false;
|
|
114
|
-
btn.textContent = btn.dataset.label || btn.textContent;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
function post(url, data){
|
|
118
|
-
return fetch(url, {method:'POST', headers:{'Content-Type':'application/json'},
|
|
119
|
-
body:JSON.stringify(data)}).then(function(r){
|
|
120
|
-
return r.json().catch(function(){ return {}; }).then(function(d){
|
|
121
|
-
return {status:r.status, data:d};
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function showStep(n){
|
|
127
|
-
$('step1').hidden = (n !== 1);
|
|
128
|
-
$('step2').hidden = (n !== 2);
|
|
129
|
-
$('s2').className = (n === 2 ? 'on' : '');
|
|
130
|
-
say('');
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
$('reqBtn').addEventListener('click', function(){
|
|
134
|
-
var u = $('email').value.trim().toLowerCase();
|
|
135
|
-
if(!u){ say('请先填申请邮箱', 'err'); return; }
|
|
136
|
-
var badMail = !/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(u) || u.indexOf('..') >= 0 || u.charAt(0) === '.';
|
|
137
|
-
if(badMail){ say('请填有效的邮箱地址', 'err'); return; }
|
|
138
|
-
var btn = this; busy(btn, true);
|
|
139
|
-
post('/api/access/request', {email:u}).then(function(res){
|
|
140
|
-
busy(btn, false);
|
|
141
|
-
if(!res.data.ok){ say(res.data.msg || '提交失败,请稍后重试', 'err'); return; }
|
|
142
|
-
sessionStorage.setItem('wb_access_email', u);
|
|
143
|
-
$('email2').value = u;
|
|
144
|
-
showStep(2);
|
|
145
|
-
$('notice').textContent = res.data.reused
|
|
146
|
-
? '该邮箱已有一份待审核的申请,请联系管理员索取之前发出的验证码。'
|
|
147
|
-
: '申请已提交,管理员会把验证码回复到这个邮箱,填入下方即可进入。';
|
|
148
|
-
$('code').focus();
|
|
149
|
-
}).catch(function(){ busy(btn, false); say('网络异常,请稍后重试', 'err'); });
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
$('verBtn').addEventListener('click', function(){
|
|
153
|
-
var u = $('email2').value.trim().toLowerCase();
|
|
154
|
-
var c = $('code').value.trim();
|
|
155
|
-
if(!u){ say('请填申请时用的邮箱', 'err'); return; }
|
|
156
|
-
if(!/^\d{6}$/.test(c)){ say('验证码是 6 位数字', 'err'); return; }
|
|
157
|
-
var btn = this; busy(btn, true);
|
|
158
|
-
post('/api/access/verify', {email:u, code:c}).then(function(res){
|
|
159
|
-
busy(btn, false);
|
|
160
|
-
if(!res.data.ok){ say(res.data.msg || '验证失败', 'err'); return; }
|
|
161
|
-
sessionStorage.removeItem('wb_access_email');
|
|
162
|
-
location.href = '/';
|
|
163
|
-
}).catch(function(){ busy(btn, false); say('网络异常,请稍后重试', 'err'); });
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
$('backBtn').addEventListener('click', function(){
|
|
167
|
-
sessionStorage.removeItem('wb_access_email');
|
|
168
|
-
$('code').value = '';
|
|
169
|
-
showStep(1);
|
|
170
|
-
$('email').focus();
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
$('adminToggle').addEventListener('click', function(){
|
|
174
|
-
$('adminBox').hidden = !$('adminBox').hidden;
|
|
175
|
-
if(!$('adminBox').hidden) $('master').focus();
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
$('masterBtn').addEventListener('click', function(){
|
|
179
|
-
var p = $('master').value;
|
|
180
|
-
if(!p){ say('请输入主口令', 'err'); return; }
|
|
181
|
-
var btn = this; busy(btn, true);
|
|
182
|
-
post('/api/access/master', {password:p}).then(function(res){
|
|
183
|
-
busy(btn, false);
|
|
184
|
-
if(!res.data.ok){ say(res.data.msg || '验证失败', 'err'); return; }
|
|
185
|
-
location.href = '/';
|
|
186
|
-
}).catch(function(){ busy(btn, false); say('网络异常,请稍后重试', 'err'); });
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
$('email').addEventListener('keydown', function(e){ if(e.key === 'Enter') $('reqBtn').click(); });
|
|
190
|
-
$('code').addEventListener('keydown', function(e){ if(e.key === 'Enter') $('verBtn').click(); });
|
|
191
|
-
$('master').addEventListener('keydown', function(e){ if(e.key === 'Enter') $('masterBtn').click(); });
|
|
192
|
-
$('code').addEventListener('input', function(){ this.value = this.value.replace(/\D/g,'').slice(0,6); });
|
|
193
|
-
|
|
194
|
-
var saved = sessionStorage.getItem('wb_access_email');
|
|
195
|
-
if(saved){ $('email').value = saved; $('email2').value = saved; showStep(2); $('code').focus(); }
|
|
196
|
-
if(new URLSearchParams(location.search).get('expired') === '1'){
|
|
197
|
-
say('登录状态已失效,请重新申请验证码', 'err');
|
|
198
|
-
}
|
|
199
|
-
})();
|
|
200
|
-
</script>
|
|
201
|
-
</body>
|
|
202
|
-
</html>
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>申请访问 · 手绘工坊号池工作台</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root{
|
|
9
|
+
--bg:#f5f3fb; --panel:#ffffff; --ink:#1f1b2e; --ink-2:#5b5573; --ink-3:#8b86a3;
|
|
10
|
+
--line:#e8e4f5; --primary:#6a5ae0; --primary-2:#8b7cf6; --pink:#ff6b9a;
|
|
11
|
+
--ok:#12b886; --err:#e03131; --chip:#f1eefe;
|
|
12
|
+
}
|
|
13
|
+
*{box-sizing:border-box}
|
|
14
|
+
[hidden]{display:none!important}
|
|
15
|
+
body{margin:0;min-height:100vh;color:var(--ink);
|
|
16
|
+
font:14px/1.7 -apple-system,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;
|
|
17
|
+
background:radial-gradient(1100px 620px at 12% -12%,#e6dfff 0%,transparent 62%),
|
|
18
|
+
radial-gradient(900px 560px at 100% 0%,#ffe7f0 0%,transparent 58%),
|
|
19
|
+
var(--bg);
|
|
20
|
+
display:flex;align-items:center;justify-content:center;padding:24px}
|
|
21
|
+
.card{width:100%;max-width:420px;background:var(--panel);border:1px solid var(--line);
|
|
22
|
+
border-radius:20px;box-shadow:0 18px 60px rgba(80,60,160,.13);padding:30px 28px 24px}
|
|
23
|
+
.brand{display:inline-flex;align-items:center;gap:8px;font-size:11px;letter-spacing:.6px;
|
|
24
|
+
color:var(--primary);background:var(--chip);border:1px solid #ddd6fb;border-radius:20px;
|
|
25
|
+
padding:5px 12px;margin-bottom:18px}
|
|
26
|
+
.brand i{width:7px;height:7px;border-radius:50%;background:var(--primary);display:block}
|
|
27
|
+
h1{font-size:22px;margin:0 0 6px;letter-spacing:.5px}
|
|
28
|
+
.lead{font-size:12.5px;color:var(--ink-2);margin:0 0 22px;line-height:1.8}
|
|
29
|
+
.lead b{color:var(--ink);font-weight:600}
|
|
30
|
+
.steps{display:flex;gap:6px;margin:0 0 20px}
|
|
31
|
+
.steps span{flex:1;height:4px;border-radius:4px;background:var(--line)}
|
|
32
|
+
.steps span.on{background:linear-gradient(90deg,var(--primary),var(--pink))}
|
|
33
|
+
label{display:block;font-size:11.5px;color:var(--ink-2);margin:0 0 7px;font-weight:600}
|
|
34
|
+
input{width:100%;border:1px solid var(--line);border-radius:11px;background:#fbfaff;
|
|
35
|
+
padding:12px 13px;font:inherit;color:var(--ink);outline:none;transition:.15s}
|
|
36
|
+
input:focus{border-color:var(--primary-2);background:#fff;box-shadow:0 0 0 3px rgba(139,124,246,.14)}
|
|
37
|
+
input.code{font-size:22px;letter-spacing:9px;text-align:center;font-weight:600;
|
|
38
|
+
font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
|
|
39
|
+
.btn{width:100%;border:0;border-radius:11px;padding:12px 14px;font:inherit;font-weight:600;
|
|
40
|
+
cursor:pointer;margin-top:14px;transition:.15s;background:#f1eefe;color:var(--primary)}
|
|
41
|
+
.btn:hover{filter:brightness(.97)}
|
|
42
|
+
.btn.primary{background:linear-gradient(135deg,var(--primary),var(--pink));color:#fff;
|
|
43
|
+
box-shadow:0 8px 20px rgba(106,90,224,.26)}
|
|
44
|
+
.btn.ghost{background:#fff;border:1px solid var(--line);color:var(--ink-2);font-weight:500}
|
|
45
|
+
.btn:disabled{opacity:.55;cursor:not-allowed}
|
|
46
|
+
.msg{margin-top:14px;font-size:12px;line-height:1.7;border-radius:10px;padding:0;min-height:0}
|
|
47
|
+
.msg:not(:empty){padding:10px 12px;border:1px solid var(--line);background:#faf9ff;color:var(--ink-2)}
|
|
48
|
+
.msg.err{border-color:#ffd6d6;background:#fff5f5;color:#c92a2a}
|
|
49
|
+
.msg.ok{border-color:#c3f0dd;background:#f2fcf8;color:#087f5b}
|
|
50
|
+
.notice{background:#f2fcf8;border:1px solid #c3f0dd;color:#087f5b;border-radius:11px;
|
|
51
|
+
padding:11px 13px;font-size:12px;line-height:1.75;margin:0 0 18px}
|
|
52
|
+
.foot{margin-top:22px;padding-top:16px;border-top:1px solid var(--line);
|
|
53
|
+
display:flex;justify-content:space-between;align-items:center;font-size:11px;color:var(--ink-3)}
|
|
54
|
+
.foot a{color:var(--ink-3);text-decoration:none;cursor:pointer;border-bottom:1px dashed var(--line)}
|
|
55
|
+
.foot a:hover{color:var(--primary)}
|
|
56
|
+
.admin{margin-top:16px;padding:14px;border:1px solid var(--line);border-radius:12px;background:#fbfaff}
|
|
57
|
+
.admin p{margin:0 0 10px;font-size:11.5px;color:var(--ink-2);line-height:1.7}
|
|
58
|
+
.hint{font-size:11px;color:var(--ink-3);margin:12px 0 0;line-height:1.7}
|
|
59
|
+
</style>
|
|
60
|
+
</head>
|
|
61
|
+
<body>
|
|
62
|
+
<div class="card">
|
|
63
|
+
<div class="brand"><i></i>手绘工坊 · 号池工作台</div>
|
|
64
|
+
<h1>申请访问</h1>
|
|
65
|
+
<p class="lead">工作台仅供受邀使用。填写你的邮箱点<b>申请访问</b>,管理员会把验证码回复到这个邮箱。收到后回到本页填入邮箱和验证码即可进入。</p>
|
|
66
|
+
<div class="steps"><span id="s1" class="on"></span><span id="s2"></span></div>
|
|
67
|
+
|
|
68
|
+
<div id="step1">
|
|
69
|
+
<label for="email">申请邮箱</label>
|
|
70
|
+
<input id="email" type="email" maxlength="254" autocomplete="email" spellcheck="false" placeholder="name@example.com">
|
|
71
|
+
<button id="reqBtn" class="btn primary" type="button">申请访问</button>
|
|
72
|
+
<p class="hint">请填能收信的邮箱,管理员会把验证码回复到这里。</p>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div id="step2" hidden>
|
|
76
|
+
<div class="notice" id="notice">申请已提交,验证码会回复到你填的邮箱。</div>
|
|
77
|
+
<label for="email2">申请时用的邮箱</label>
|
|
78
|
+
<input id="email2" type="email" maxlength="254" autocomplete="email" spellcheck="false">
|
|
79
|
+
<label for="code" style="margin-top:14px">验证码</label>
|
|
80
|
+
<input id="code" class="code" type="text" inputmode="numeric" autocomplete="one-time-code" placeholder="000000">
|
|
81
|
+
<button id="verBtn" class="btn primary" type="button">进入工作台</button>
|
|
82
|
+
<button id="backBtn" class="btn ghost" type="button">换一个邮箱重新申请</button>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<div id="msg" class="msg" role="status"></div>
|
|
86
|
+
|
|
87
|
+
<div class="foot">
|
|
88
|
+
<span>验证码 24 小时有效 · 一次性 · 与邮箱绑定</span>
|
|
89
|
+
<a id="adminToggle" type="button">管理员入口</a>
|
|
90
|
+
</div>
|
|
91
|
+
<div id="adminBox" class="admin" hidden>
|
|
92
|
+
<p>管理员可凭主口令直接进入,不需要申请验证码。主口令只保存在服务器上,请勿写进共享文档。</p>
|
|
93
|
+
<label for="master">主口令</label>
|
|
94
|
+
<input id="master" type="password" autocomplete="current-password" placeholder="输入主口令">
|
|
95
|
+
<button id="masterBtn" class="btn" type="button">进入工作台</button>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<script>
|
|
100
|
+
(function(){
|
|
101
|
+
var $ = function(id){ return document.getElementById(id); };
|
|
102
|
+
var msg = $('msg');
|
|
103
|
+
function say(t, cls){
|
|
104
|
+
msg.textContent = t || '';
|
|
105
|
+
msg.className = 'msg' + (cls ? ' ' + cls : '');
|
|
106
|
+
}
|
|
107
|
+
function busy(btn, on){
|
|
108
|
+
if(on){
|
|
109
|
+
if(!btn.dataset.label) btn.dataset.label = btn.textContent;
|
|
110
|
+
btn.disabled = true;
|
|
111
|
+
btn.textContent = '处理中…';
|
|
112
|
+
}else{
|
|
113
|
+
btn.disabled = false;
|
|
114
|
+
btn.textContent = btn.dataset.label || btn.textContent;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function post(url, data){
|
|
118
|
+
return fetch(url, {method:'POST', headers:{'Content-Type':'application/json'},
|
|
119
|
+
body:JSON.stringify(data)}).then(function(r){
|
|
120
|
+
return r.json().catch(function(){ return {}; }).then(function(d){
|
|
121
|
+
return {status:r.status, data:d};
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function showStep(n){
|
|
127
|
+
$('step1').hidden = (n !== 1);
|
|
128
|
+
$('step2').hidden = (n !== 2);
|
|
129
|
+
$('s2').className = (n === 2 ? 'on' : '');
|
|
130
|
+
say('');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
$('reqBtn').addEventListener('click', function(){
|
|
134
|
+
var u = $('email').value.trim().toLowerCase();
|
|
135
|
+
if(!u){ say('请先填申请邮箱', 'err'); return; }
|
|
136
|
+
var badMail = !/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(u) || u.indexOf('..') >= 0 || u.charAt(0) === '.';
|
|
137
|
+
if(badMail){ say('请填有效的邮箱地址', 'err'); return; }
|
|
138
|
+
var btn = this; busy(btn, true);
|
|
139
|
+
post('/api/access/request', {email:u}).then(function(res){
|
|
140
|
+
busy(btn, false);
|
|
141
|
+
if(!res.data.ok){ say(res.data.msg || '提交失败,请稍后重试', 'err'); return; }
|
|
142
|
+
sessionStorage.setItem('wb_access_email', u);
|
|
143
|
+
$('email2').value = u;
|
|
144
|
+
showStep(2);
|
|
145
|
+
$('notice').textContent = res.data.reused
|
|
146
|
+
? '该邮箱已有一份待审核的申请,请联系管理员索取之前发出的验证码。'
|
|
147
|
+
: '申请已提交,管理员会把验证码回复到这个邮箱,填入下方即可进入。';
|
|
148
|
+
$('code').focus();
|
|
149
|
+
}).catch(function(){ busy(btn, false); say('网络异常,请稍后重试', 'err'); });
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
$('verBtn').addEventListener('click', function(){
|
|
153
|
+
var u = $('email2').value.trim().toLowerCase();
|
|
154
|
+
var c = $('code').value.trim();
|
|
155
|
+
if(!u){ say('请填申请时用的邮箱', 'err'); return; }
|
|
156
|
+
if(!/^\d{6}$/.test(c)){ say('验证码是 6 位数字', 'err'); return; }
|
|
157
|
+
var btn = this; busy(btn, true);
|
|
158
|
+
post('/api/access/verify', {email:u, code:c}).then(function(res){
|
|
159
|
+
busy(btn, false);
|
|
160
|
+
if(!res.data.ok){ say(res.data.msg || '验证失败', 'err'); return; }
|
|
161
|
+
sessionStorage.removeItem('wb_access_email');
|
|
162
|
+
location.href = '/';
|
|
163
|
+
}).catch(function(){ busy(btn, false); say('网络异常,请稍后重试', 'err'); });
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
$('backBtn').addEventListener('click', function(){
|
|
167
|
+
sessionStorage.removeItem('wb_access_email');
|
|
168
|
+
$('code').value = '';
|
|
169
|
+
showStep(1);
|
|
170
|
+
$('email').focus();
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
$('adminToggle').addEventListener('click', function(){
|
|
174
|
+
$('adminBox').hidden = !$('adminBox').hidden;
|
|
175
|
+
if(!$('adminBox').hidden) $('master').focus();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
$('masterBtn').addEventListener('click', function(){
|
|
179
|
+
var p = $('master').value;
|
|
180
|
+
if(!p){ say('请输入主口令', 'err'); return; }
|
|
181
|
+
var btn = this; busy(btn, true);
|
|
182
|
+
post('/api/access/master', {password:p}).then(function(res){
|
|
183
|
+
busy(btn, false);
|
|
184
|
+
if(!res.data.ok){ say(res.data.msg || '验证失败', 'err'); return; }
|
|
185
|
+
location.href = '/';
|
|
186
|
+
}).catch(function(){ busy(btn, false); say('网络异常,请稍后重试', 'err'); });
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
$('email').addEventListener('keydown', function(e){ if(e.key === 'Enter') $('reqBtn').click(); });
|
|
190
|
+
$('code').addEventListener('keydown', function(e){ if(e.key === 'Enter') $('verBtn').click(); });
|
|
191
|
+
$('master').addEventListener('keydown', function(e){ if(e.key === 'Enter') $('masterBtn').click(); });
|
|
192
|
+
$('code').addEventListener('input', function(){ this.value = this.value.replace(/\D/g,'').slice(0,6); });
|
|
193
|
+
|
|
194
|
+
var saved = sessionStorage.getItem('wb_access_email');
|
|
195
|
+
if(saved){ $('email').value = saved; $('email2').value = saved; showStep(2); $('code').focus(); }
|
|
196
|
+
if(new URLSearchParams(location.search).get('expired') === '1'){
|
|
197
|
+
say('登录状态已失效,请重新申请验证码', 'err');
|
|
198
|
+
}
|
|
199
|
+
})();
|
|
200
|
+
</script>
|
|
201
|
+
</body>
|
|
202
|
+
</html>
|
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
# ============================================
|
|
2
|
-
# ChatGPT2API 环境变量配置示例
|
|
3
|
-
# ============================================
|
|
4
|
-
|
|
5
|
-
# 认证密钥(必填)
|
|
6
|
-
CHATGPT2API_AUTH_KEY=your_secret_key_here
|
|
7
|
-
|
|
8
|
-
# 基础 URL(可选,用于生成图片 URL)
|
|
9
|
-
# CHATGPT2API_BASE_URL=https://your-domain.com
|
|
10
|
-
|
|
11
|
-
# ============================================
|
|
12
|
-
# 存储后端配置
|
|
13
|
-
# ============================================
|
|
14
|
-
|
|
15
|
-
# 存储后端类型(可选值: json, sqlite, postgres, git)
|
|
16
|
-
# 默认: json
|
|
17
|
-
STORAGE_BACKEND=json
|
|
18
|
-
|
|
19
|
-
# ============================================
|
|
20
|
-
# 数据库配置(当 STORAGE_BACKEND=sqlite/postgres 时使用)
|
|
21
|
-
# ============================================
|
|
22
|
-
|
|
23
|
-
# PostgreSQL 示例
|
|
24
|
-
# DATABASE_URL=postgresql://user:password@localhost:5432/chatgpt2api
|
|
25
|
-
|
|
26
|
-
# Supabase 示例
|
|
27
|
-
# DATABASE_URL=postgresql://postgres.xxx:password@aws-1-us-west-1.pooler.supabase.com:5432/postgres
|
|
28
|
-
|
|
29
|
-
# SQLite 示例(不指定时自动使用 data/accounts.db)
|
|
30
|
-
# DATABASE_URL=sqlite:///app/data/accounts.db
|
|
31
|
-
|
|
32
|
-
# ============================================
|
|
33
|
-
# Git 仓库配置(当 STORAGE_BACKEND=git 时使用)
|
|
34
|
-
# ============================================
|
|
35
|
-
|
|
36
|
-
# Git 仓库地址(必填)
|
|
37
|
-
# GIT_REPO_URL=https://github.com/your-username/your-private-repo.git
|
|
38
|
-
|
|
39
|
-
# Git 访问令牌(必填)
|
|
40
|
-
# GitHub: ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
41
|
-
# GitLab: glpat-xxxxxxxxxxxxxxxxxxxx
|
|
42
|
-
# GIT_TOKEN=your_git_token_here
|
|
43
|
-
|
|
44
|
-
# Git 分支(可选,默认: main)
|
|
45
|
-
# GIT_BRANCH=main
|
|
46
|
-
|
|
47
|
-
# Git 仓库中的文件路径(可选,默认: accounts.json)
|
|
48
|
-
# GIT_FILE_PATH=accounts.json
|
|
49
|
-
|
|
50
|
-
# ============================================
|
|
51
|
-
# WARP / FlareSolverr 稳定代理配置(可选)
|
|
52
|
-
# ============================================
|
|
53
|
-
|
|
54
|
-
# docker-compose.warp.yml 暴露到宿主机的端口
|
|
55
|
-
# WARP_SOCKS_PORT=40000
|
|
56
|
-
# PRIVOXY_PORT=40080
|
|
57
|
-
# FLARESOLVERR_PORT=8191
|
|
58
|
-
|
|
59
|
-
# FlareSolverr 日志与时区
|
|
60
|
-
# FLARESOLVERR_LOG_LEVEL=info
|
|
61
|
-
# TZ=Asia/Shanghai
|
|
62
|
-
|
|
63
|
-
# Cloudflare WARP+ License Key(可选)
|
|
64
|
-
# WARP_LICENSE_KEY=
|
|
65
|
-
|
|
66
|
-
# 初始化 proxy_runtime 默认值
|
|
67
|
-
# CHATGPT2API_PROXY_RUNTIME_ENABLED=true
|
|
68
|
-
# CHATGPT2API_PROXY_RUNTIME_EGRESS_MODE=single_proxy
|
|
69
|
-
# CHATGPT2API_PROXY_RUNTIME_PROXY_URL=http://privoxy:8118
|
|
70
|
-
# CHATGPT2API_PROXY_RUNTIME_RESOURCE_PROXY_URL=
|
|
71
|
-
# CHATGPT2API_PROXY_RUNTIME_SKIP_SSL_VERIFY=false
|
|
72
|
-
# CHATGPT2API_PROXY_RUNTIME_RESET_STATUS_CODES=403
|
|
73
|
-
|
|
74
|
-
# Cloudflare clearance 刷新配置
|
|
75
|
-
# CHATGPT2API_PROXY_RUNTIME_CLEARANCE_ENABLED=true
|
|
76
|
-
# CHATGPT2API_PROXY_RUNTIME_CLEARANCE_MODE=flaresolverr
|
|
77
|
-
# CHATGPT2API_FLARESOLVERR_URL=http://flaresolverr:8191
|
|
78
|
-
# CHATGPT2API_PROXY_RUNTIME_CLEARANCE_TIMEOUT_SEC=60
|
|
79
|
-
# CHATGPT2API_PROXY_RUNTIME_CLEARANCE_REFRESH_INTERVAL=3600
|
|
80
|
-
# CHATGPT2API_PROXY_RUNTIME_WARM_UP_ON_START=false
|
|
81
|
-
# CHATGPT2API_PROXY_RUNTIME_BROWSER=chrome
|
|
82
|
-
# CHATGPT2API_PROXY_RUNTIME_USER_AGENT=
|
|
1
|
+
# ============================================
|
|
2
|
+
# ChatGPT2API 环境变量配置示例
|
|
3
|
+
# ============================================
|
|
4
|
+
|
|
5
|
+
# 认证密钥(必填)
|
|
6
|
+
CHATGPT2API_AUTH_KEY=your_secret_key_here
|
|
7
|
+
|
|
8
|
+
# 基础 URL(可选,用于生成图片 URL)
|
|
9
|
+
# CHATGPT2API_BASE_URL=https://your-domain.com
|
|
10
|
+
|
|
11
|
+
# ============================================
|
|
12
|
+
# 存储后端配置
|
|
13
|
+
# ============================================
|
|
14
|
+
|
|
15
|
+
# 存储后端类型(可选值: json, sqlite, postgres, git)
|
|
16
|
+
# 默认: json
|
|
17
|
+
STORAGE_BACKEND=json
|
|
18
|
+
|
|
19
|
+
# ============================================
|
|
20
|
+
# 数据库配置(当 STORAGE_BACKEND=sqlite/postgres 时使用)
|
|
21
|
+
# ============================================
|
|
22
|
+
|
|
23
|
+
# PostgreSQL 示例
|
|
24
|
+
# DATABASE_URL=postgresql://user:password@localhost:5432/chatgpt2api
|
|
25
|
+
|
|
26
|
+
# Supabase 示例
|
|
27
|
+
# DATABASE_URL=postgresql://postgres.xxx:password@aws-1-us-west-1.pooler.supabase.com:5432/postgres
|
|
28
|
+
|
|
29
|
+
# SQLite 示例(不指定时自动使用 data/accounts.db)
|
|
30
|
+
# DATABASE_URL=sqlite:///app/data/accounts.db
|
|
31
|
+
|
|
32
|
+
# ============================================
|
|
33
|
+
# Git 仓库配置(当 STORAGE_BACKEND=git 时使用)
|
|
34
|
+
# ============================================
|
|
35
|
+
|
|
36
|
+
# Git 仓库地址(必填)
|
|
37
|
+
# GIT_REPO_URL=https://github.com/your-username/your-private-repo.git
|
|
38
|
+
|
|
39
|
+
# Git 访问令牌(必填)
|
|
40
|
+
# GitHub: ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
41
|
+
# GitLab: glpat-xxxxxxxxxxxxxxxxxxxx
|
|
42
|
+
# GIT_TOKEN=your_git_token_here
|
|
43
|
+
|
|
44
|
+
# Git 分支(可选,默认: main)
|
|
45
|
+
# GIT_BRANCH=main
|
|
46
|
+
|
|
47
|
+
# Git 仓库中的文件路径(可选,默认: accounts.json)
|
|
48
|
+
# GIT_FILE_PATH=accounts.json
|
|
49
|
+
|
|
50
|
+
# ============================================
|
|
51
|
+
# WARP / FlareSolverr 稳定代理配置(可选)
|
|
52
|
+
# ============================================
|
|
53
|
+
|
|
54
|
+
# docker-compose.warp.yml 暴露到宿主机的端口
|
|
55
|
+
# WARP_SOCKS_PORT=40000
|
|
56
|
+
# PRIVOXY_PORT=40080
|
|
57
|
+
# FLARESOLVERR_PORT=8191
|
|
58
|
+
|
|
59
|
+
# FlareSolverr 日志与时区
|
|
60
|
+
# FLARESOLVERR_LOG_LEVEL=info
|
|
61
|
+
# TZ=Asia/Shanghai
|
|
62
|
+
|
|
63
|
+
# Cloudflare WARP+ License Key(可选)
|
|
64
|
+
# WARP_LICENSE_KEY=
|
|
65
|
+
|
|
66
|
+
# 初始化 proxy_runtime 默认值
|
|
67
|
+
# CHATGPT2API_PROXY_RUNTIME_ENABLED=true
|
|
68
|
+
# CHATGPT2API_PROXY_RUNTIME_EGRESS_MODE=single_proxy
|
|
69
|
+
# CHATGPT2API_PROXY_RUNTIME_PROXY_URL=http://privoxy:8118
|
|
70
|
+
# CHATGPT2API_PROXY_RUNTIME_RESOURCE_PROXY_URL=
|
|
71
|
+
# CHATGPT2API_PROXY_RUNTIME_SKIP_SSL_VERIFY=false
|
|
72
|
+
# CHATGPT2API_PROXY_RUNTIME_RESET_STATUS_CODES=403
|
|
73
|
+
|
|
74
|
+
# Cloudflare clearance 刷新配置
|
|
75
|
+
# CHATGPT2API_PROXY_RUNTIME_CLEARANCE_ENABLED=true
|
|
76
|
+
# CHATGPT2API_PROXY_RUNTIME_CLEARANCE_MODE=flaresolverr
|
|
77
|
+
# CHATGPT2API_FLARESOLVERR_URL=http://flaresolverr:8191
|
|
78
|
+
# CHATGPT2API_PROXY_RUNTIME_CLEARANCE_TIMEOUT_SEC=60
|
|
79
|
+
# CHATGPT2API_PROXY_RUNTIME_CLEARANCE_REFRESH_INTERVAL=3600
|
|
80
|
+
# CHATGPT2API_PROXY_RUNTIME_WARM_UP_ON_START=false
|
|
81
|
+
# CHATGPT2API_PROXY_RUNTIME_BROWSER=chrome
|
|
82
|
+
# CHATGPT2API_PROXY_RUNTIME_USER_AGENT=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
3.13
|
|
1
|
+
3.13
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 kunkun
|
|
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.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 kunkun
|
|
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.
|