From 8633addf646cdea9449f7e1f7760d27f9facc9b1 Mon Sep 17 00:00:00 2001 From: chiyi Date: Fri, 26 Jun 2026 00:02:14 +0800 Subject: [PATCH] docs: expand repo structure with subdirectories; drop stray adobe.zip Co-Authored-By: Claude Opus 4.8 --- .gitignore | 2 ++ README.en.md | 43 ++++++++++++++++++++++++---- README.md | 43 ++++++++++++++++++++++++---- backend/internal/provider/adobe.zip | Bin 11843 -> 0 bytes 4 files changed, 78 insertions(+), 10 deletions(-) delete mode 100644 backend/internal/provider/adobe.zip diff --git a/.gitignore b/.gitignore index fabb045..a89d7e9 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,8 @@ api_test_video.py # hardcoded API key # ====================================================================== # browser HAR captures contain real cookies/tokens *.har +# stray source/backup archives +*.zip # prebuilt binaries (backend is built from source now) /dist/ # stray debug screenshots pasted into the repo root diff --git a/README.en.md b/README.en.md index e8da224..2889a7c 100644 --- a/README.en.md +++ b/README.en.md @@ -218,11 +218,44 @@ server { ## ๐Ÿ“ฆ Repository Layout ``` -frontend/ Frontend source (Vue 3) -backend/ Backend source (Go, entry point at cmd/api) -docker-compose.yml Docker orchestration (Postgres/Redis/RustFS/backend/frontend/acme) -install.sh One-command deploy script -.env.docker.example Environment variable template +backend/ Backend source (Go) +โ”œโ”€โ”€ cmd/ +โ”‚ โ”œโ”€โ”€ api/ Service entry point (main) +โ”‚ โ””โ”€โ”€ marklabel/ Ops helper (mark accounts on demand) +โ”œโ”€โ”€ internal/ +โ”‚ โ”œโ”€โ”€ bootstrap/ App wiring, scheduled maintenance startup +โ”‚ โ”œโ”€โ”€ config/ Env-var configuration loading +โ”‚ โ”œโ”€โ”€ http/ +โ”‚ โ”‚ โ”œโ”€โ”€ handler/ HTTP handlers (v1-compatible API, admin, authโ€ฆ) +โ”‚ โ”‚ โ”œโ”€โ”€ middleware/ Auth / request-id middleware +โ”‚ โ”‚ โ””โ”€โ”€ router/ Route registration +โ”‚ โ”œโ”€โ”€ model/ GORM data models +โ”‚ โ”œโ”€โ”€ provider/ Upstream provider clients +โ”‚ โ”‚ โ”œโ”€โ”€ adobe/ Adobe Firefly (tls-client fingerprint) +โ”‚ โ”‚ โ”œโ”€โ”€ chatgpt/ OpenAI (incl. PoW / turnstile) +โ”‚ โ”‚ โ”œโ”€โ”€ runway/ Runway video +โ”‚ โ”‚ โ”œโ”€โ”€ leonardo/ Leonardo +โ”‚ โ”‚ โ”œโ”€โ”€ krea/ Krea +โ”‚ โ”‚ โ””โ”€โ”€ imagine/ Imagine.art +โ”‚ โ”œโ”€โ”€ repo/ Data-access layer (users / models / accounts / logs / CDKโ€ฆ) +โ”‚ โ”œโ”€โ”€ service/ Business logic (scheduling, billing, account pools, keep-alive, maintenance) +โ”‚ โ””โ”€โ”€ storage/ RustFS / S3 media storage +โ”œโ”€โ”€ Dockerfile Multi-stage build (compile source โ†’ slim runtime image) +โ””โ”€โ”€ .env.example Backend env-var template + +frontend/ Frontend source (Vue 3 + Vite) +โ”œโ”€โ”€ src/ +โ”‚ โ”œโ”€โ”€ views/ Pages (playground / accounts / models / logs / overview / usersโ€ฆ) +โ”‚ โ”œโ”€โ”€ components/ Reusable components (modals / selectors / lightboxโ€ฆ) +โ”‚ โ”œโ”€โ”€ layouts/ Public / admin layouts +โ”‚ โ”œโ”€โ”€ utils/ Utility functions +โ”‚ โ””โ”€โ”€ api.js ยท auth.js โ€ฆ API client, auth, theme, credits, etc. +โ”œโ”€โ”€ Dockerfile Nginx static hosting + cert watcher +โ””โ”€โ”€ default.conf.template Nginx site template (reverse proxy + caching) + +docker-compose.yml Docker orchestration (Postgres / Redis / RustFS / backend / frontend / acme) +install.sh One-command deploy script (= docker compose up -d --build) +.env.docker.example Deployment env-var template ``` ## ๐Ÿ—บ๏ธ Roadmap diff --git a/README.md b/README.md index 972f197..631a45e 100644 --- a/README.md +++ b/README.md @@ -218,11 +218,44 @@ server { ## ๐Ÿ“ฆ ไป“ๅบ“็ป“ๆž„ ``` -frontend/ ๅ‰็ซฏๆบ็ (Vue 3) -backend/ ๅŽ็ซฏๆบ็ (Go,cmd/api ไธบๅ…ฅๅฃ) -docker-compose.yml Docker ็ผ–ๆŽ’(Postgres/Redis/RustFS/ๅŽ็ซฏ/ๅ‰็ซฏ/acme) -install.sh ไธ€้”ฎ้ƒจ็ฝฒ่„šๆœฌ -.env.docker.example ็Žฏๅขƒๅ˜้‡ๆจกๆฟ +backend/ ๅŽ็ซฏๆบ็ (Go) +โ”œโ”€โ”€ cmd/ +โ”‚ โ”œโ”€โ”€ api/ ๆœๅŠกๅ…ฅๅฃ(main) +โ”‚ โ””โ”€โ”€ marklabel/ ่ฟ็ปดๅฐๅทฅๅ…ท(ๆŒ‰้œ€ๆ ‡่ฎฐ่ดฆๅท) +โ”œโ”€โ”€ internal/ +โ”‚ โ”œโ”€โ”€ bootstrap/ ๅบ”็”จ่ฃ…้…ใ€ๅฎšๆ—ถ็ปดๆŠคไปปๅŠกๅฏๅŠจ +โ”‚ โ”œโ”€โ”€ config/ ็Žฏๅขƒๅ˜้‡้…็ฝฎๅŠ ่ฝฝ +โ”‚ โ”œโ”€โ”€ http/ +โ”‚ โ”‚ โ”œโ”€โ”€ handler/ HTTP ๅค„็†ๅ™จ(v1 ๅ…ผๅฎนๆŽฅๅฃใ€ๅŽๅฐใ€้‰ดๆƒโ€ฆ) +โ”‚ โ”‚ โ”œโ”€โ”€ middleware/ ้‰ดๆƒ / ่ฏทๆฑ‚ ID ็ญ‰ไธญ้—ดไปถ +โ”‚ โ”‚ โ””โ”€โ”€ router/ ่ทฏ็”ฑๆณจๅ†Œ +โ”‚ โ”œโ”€โ”€ model/ GORM ๆ•ฐๆฎๆจกๅž‹ +โ”‚ โ”œโ”€โ”€ provider/ ๅ„ไธŠๆธธไพ›ๅบ”ๅ•†ๅฎขๆˆท็ซฏ +โ”‚ โ”‚ โ”œโ”€โ”€ adobe/ Adobe Firefly(tls-client ๆŒ‡็บน) +โ”‚ โ”‚ โ”œโ”€โ”€ chatgpt/ OpenAI(ๅซ PoW / turnstile) +โ”‚ โ”‚ โ”œโ”€โ”€ runway/ Runway ่ง†้ข‘ +โ”‚ โ”‚ โ”œโ”€โ”€ leonardo/ Leonardo +โ”‚ โ”‚ โ”œโ”€โ”€ krea/ Krea +โ”‚ โ”‚ โ””โ”€โ”€ imagine/ Imagine.art +โ”‚ โ”œโ”€โ”€ repo/ ๆ•ฐๆฎ่ฎฟ้—ฎๅฑ‚(็”จๆˆท / ๆจกๅž‹ / ่ดฆๅท / ๆ—ฅๅฟ— / CDKโ€ฆ) +โ”‚ โ”œโ”€โ”€ service/ ไธšๅŠก้€ป่พ‘(็”Ÿๆˆ่ฐƒๅบฆใ€่ฎก่ดนใ€่ดฆๅทๆฑ ใ€ไฟๆดปใ€็ปดๆŠค) +โ”‚ โ””โ”€โ”€ storage/ RustFS / S3 ๅช’ไฝ“ๅญ˜ๅ‚จ +โ”œโ”€โ”€ Dockerfile ๅคš้˜ถๆฎตๆž„ๅปบ(ๆบ็ ็ผ–่ฏ‘ โ†’ ็ฒพ็ฎ€่ฟ่กŒ้•œๅƒ) +โ””โ”€โ”€ .env.example ๅŽ็ซฏ็Žฏๅขƒๅ˜้‡ๆจกๆฟ + +frontend/ ๅ‰็ซฏๆบ็ (Vue 3 + Vite) +โ”œโ”€โ”€ src/ +โ”‚ โ”œโ”€โ”€ views/ ้กต้ข(็”ปๅ›พๅฐ / ่ดฆๅท / ๆจกๅž‹ / ๆ—ฅๅฟ— / ๆฆ‚่งˆ / ็”จๆˆทโ€ฆ) +โ”‚ โ”œโ”€โ”€ components/ ๅค็”จ็ป„ไปถ(ๅผน็ช— / ้€‰ๆ‹ฉๅ™จ / ็ฏ็ฎฑโ€ฆ) +โ”‚ โ”œโ”€โ”€ layouts/ ๅ…ฌๅ…ฑ / ๅŽๅฐๅธƒๅฑ€ +โ”‚ โ”œโ”€โ”€ utils/ ๅทฅๅ…ทๅ‡ฝๆ•ฐ +โ”‚ โ””โ”€โ”€ api.js ยท auth.js โ€ฆ ๆŽฅๅฃๅฐ่ฃ…ใ€้‰ดๆƒใ€ไธป้ข˜ใ€็งฏๅˆ†็ญ‰ +โ”œโ”€โ”€ Dockerfile Nginx ้™ๆ€ๆ‰˜็ฎก + ่ฏไนฆ็›‘ๅฌ +โ””โ”€โ”€ default.conf.template Nginx ็ซ™็‚นๆจกๆฟ(ๅไปฃ + ็ผ“ๅญ˜็ญ–็•ฅ) + +docker-compose.yml Docker ็ผ–ๆŽ’(Postgres / Redis / RustFS / ๅŽ็ซฏ / ๅ‰็ซฏ / acme) +install.sh ไธ€้”ฎ้ƒจ็ฝฒ่„šๆœฌ(= docker compose up -d --build) +.env.docker.example ้ƒจ็ฝฒ็Žฏๅขƒๅ˜้‡ๆจกๆฟ ``` ## ๐Ÿ—บ๏ธ Roadmap diff --git a/backend/internal/provider/adobe.zip b/backend/internal/provider/adobe.zip deleted file mode 100644 index 5ef5be12df1df018bbbd6cc983c7ea022510ba4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11843 zcmaL71#lg`)}?*S%*@Qpbj%bpGc&}@j4|6WGsVmtGjr^iIc8=!X2&?mo%!zE``5gG zca@~>s(wmRZEdwyEoC_fNKC-r>!E8!|6h&&Q$Pbq0Vd{-rWP#jUI+j%$iJ`uRcNRq z0boR)1#GYDfwl$S?6%7PV!#4m0mrGc|HVN1H^ao;&6?TD@&AS5^kui*{XZyoH5H{b zR@8v6fnn)okR@>SHd*u<7~sWZ1xTW!#Hi7+t_lhmYmK?Z7Q4MyggkviOA!x#j~kwk z8wOl^1ey>QsXhQPiKCT;t1 zyw#h@`-xltuRzwKH0b&%L)aLi3ypMR7_X!Uvu8n`$4-l2amM%+*|WOhxB0TYO7x-k6;eS&+~by0T<^+jh-eCRvm zGHAHNh>E7##)BUxae_zUo9s~#(|+I7OD$D_Z21mbXn2bNA3kZ(+I8p?DgoG0jfViC*owtFQ8=X5Ifc45yb!)w;hN32mslnv z4xK@+m0D-a<+!k8NAz4L{d|LG!C5CrO8zZd!piQ1HY75lsM=p5WlBHq3;>%P?G)2r zs`yr#_0r@?tzs%+X0m^bPu-pxN>ZafTfXbhE{=dQd z|6Kqm{|;U=I~xlJw|@xVzboNy`2MXg1V5{-{YcBdt~*xIK&M+yBf~58$T(}4gl#wB zG0}!iMq!R-kh8BQm5V0EO_E!Dk9-Szk$cFQM-jA-`BLoQQNV8OneW>1;`Zn*haqrT z;@Y3NCyB9n_WPDsmfiA!J9bQAL=8fyO(o;{ELMn`#~B-GKJ(V@1;=i?fWSMzi!JB+ zZ2S?$22)i$Ndhi0b1Lc!$<9@R)gTZKWR^u0Btn`gd?Z!Z%J#D{0}m&F`zK8c!DK}8 z@qp_<1xffIod>uRcCo|uEvp_hEC2#5xOllAagQ?V8LW2Y^xk-k&Y5hI##LBAFktZ5 zY6y`~Xaf(qEMTCle{$Q~PN|H$VfvwHXR&GL)@yq@xa?oo|K{?oXFgQ6Bd%YWl}DL*Z+vmN}#H8A_|V%$XttDc2@;l7#ak@$BT~mqdR` zma@2|x^vovR6I@tdB!8Zhi;+1%MdG~U+VW9CC`U4@%LychD3M@%Xql11dUHeMlsls z+=SW87*B|nS3rzzaWD?NOasSr-p(?U%kUo4cKju1N3b%6{6|$HdB-Mg5IwU6ZZ+5S z-7Vqu0bpqD;NBF$8g$CI`Ea7wc+9TOR;s);dLb5~ZaWcf{RKJ(R>p<1EGDSMS7@5! z$qZWu75iQchxT>p8$&r4a4HaLKX!5k33FCPkx*Sv?E!OKb`h`e+Vem+JVq_jEby*r z$Q(e^ikb}eF%|G(+sI}(AsdBBC$Emmm)a03U|<4$YRv2=K`qWjrsbBreV(| z*$4GdQ)%37u?<^b=NFn-#-evWsFo>9N-nAeeZAMiO3|zTvG92As5IMvqeAFh@EWI7 z(cg#lwgRA8J_-ywco?=pbtT(f81RsqXcq7BdOVb9#752)F6qgaV!VSGQa=Au_a*#H z%f5?!`0*PKye_NJurAm1gF8H*OHg`;f1-}tn0Wh0&vAGhaejg3;?`FGY{>60CnvdA z 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%0AX{5Szv( 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 dDJ}m&{!Poua!}BJ=N;