Skip to content

Commit 968f37a

Browse files
committed
整理代码并提交
0 parents  commit 968f37a

File tree

309 files changed

+46134
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

309 files changed

+46134
-0
lines changed

.dockerignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
.git
2+
.github
3+
.codex
4+
.venv
5+
.pytest_cache
6+
**/__pycache__/
7+
8+
# Env / secrets
9+
.env
10+
.env.*
11+
!deploy/.env.example
12+
13+
data/
14+
issues/
15+
plan/
16+
docs/
17+
参考资料/
18+
19+
frontend/node_modules/
20+
frontend/dist/
21+
22+
backend/.pytest_cache/
23+
24+
_tmp_append_test.md

.github/workflows/ci.yml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: ci
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- test
8+
pull_request:
9+
10+
concurrency:
11+
group: ci-${{ github.ref }}
12+
cancel-in-progress: true
13+
14+
jobs:
15+
backend-tests:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- uses: actions/setup-python@v5
21+
with:
22+
python-version: "3.11"
23+
cache: pip
24+
cache-dependency-path: requirements-dev.txt
25+
26+
- name: Install dependencies
27+
run: python -m pip install -r requirements-dev.txt
28+
29+
- name: Compile
30+
run: python -m compileall -q backend
31+
32+
- name: Tests
33+
run: python -m pytest -q backend/tests
34+
35+
frontend-tests:
36+
runs-on: ubuntu-latest
37+
steps:
38+
- uses: actions/checkout@v4
39+
40+
- uses: actions/setup-node@v4
41+
with:
42+
node-version: "20"
43+
cache: npm
44+
cache-dependency-path: frontend/package-lock.json
45+
46+
- name: Install dependencies
47+
run: npm ci
48+
working-directory: frontend
49+
50+
- name: Lint
51+
run: npm run lint
52+
working-directory: frontend
53+
54+
- name: Typecheck
55+
run: npm run typecheck
56+
working-directory: frontend
57+
58+
- name: Tests
59+
run: npm test
60+
working-directory: frontend
61+
62+
compose-config:
63+
runs-on: ubuntu-latest
64+
steps:
65+
- uses: actions/checkout@v4
66+
67+
- name: Prepare deploy env file
68+
run: |
69+
if [ ! -f deploy/.env ]; then
70+
cp deploy/.env.example deploy/.env
71+
fi
72+
73+
- name: Validate docker compose config
74+
run: docker compose -f deploy/docker-compose.yml config > /dev/null

.gitignore

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
## Python
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
.pytest_cache/
6+
.mypy_cache/
7+
.ruff_cache/
8+
*.egg-info/
9+
.coverage
10+
.coverage.*
11+
htmlcov/
12+
coverage.xml
13+
14+
## Virtualenv
15+
.venv/
16+
venv/
17+
ENV/
18+
env/
19+
20+
## Node
21+
node_modules/
22+
dist/
23+
.vite/
24+
25+
## Runtime data / local state (never commit)
26+
data/
27+
backend/data/
28+
deploy/.env
29+
.env
30+
.env.*
31+
!.env.example
32+
!deploy/.env.example
33+
*.db
34+
*.sqlite
35+
*.sqlite3
36+
37+
## Codex / AI tooling (repo-local)
38+
.codex/
39+
plan/
40+
issues/
41+
docs/
42+
参考资料/
43+
44+
## Data exports / plans
45+
*.csv
46+
*.tsv
47+
*.plan.md
48+
49+
## OS / IDE
50+
.DS_Store
51+
Thumbs.db
52+
desktop.ini
53+
.idea/
54+
.vscode/
55+
*.iml
56+
57+
## Local temp / scratch
58+
*.log
59+
*.tmp
60+
要求.txt
61+
_tmp_easy_export.txt
62+
_tmp_*.md
63+
_tmp_*.txt
64+
65+
## Keep public-facing docs at repo root
66+
/*.md
67+
!README.md
68+
!LICENSE*

README.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Random Mage (new-pixiv-api)
2+
3+
一个自托管的随机图片 API:把 Pixiv 原图链接导入到本地数据库后,即可通过 `/random`**标签 / 热度 / 分辨率 / R18 / AI / 作品类型** 等条件组合筛选并随机出图;同时提供管理后台(Web UI)+ 后台 Worker,用于导入、补全元数据、代理探测等任务。
4+
5+
> 免责声明:本项目为非官方实现;请遵守 Pixiv ToS/版权与当地法律法规,自行承担使用风险。不要将任何 refresh_token / 密钥 / 代理密码提交到仓库。
6+
7+
## 功能概览
8+
9+
- 公共 API
10+
- `GET /random`:默认直接返回图片流;也可 `format=json|simple_json` 返回 JSON;支持大量筛选参数
11+
- `GET /images` / `GET /images/{id}`:按条件分页查看已入库图片
12+
- `GET /i/{image_id}.{ext}`:本地代理/缓存路径(`/random?redirect=1` 会跳转到这里)
13+
- `GET /tags``GET /authors``GET /healthz``GET /version``GET /docs`(人类可读文档页)
14+
- Swagger / OpenAPI:`GET /api/docs``GET /openapi.json`
15+
- 管理后台(`/admin`
16+
- 登录后可管理:Pixiv refresh_token、代理池、导入、任务队列、运行时开关、审计/统计等
17+
- Worker(后台任务)
18+
- 导入图片 URL、补全元数据(tags/宽高/浏览收藏等)、修复失效 URL、代理探测等
19+
- 可选能力
20+
- 公网访问保护:启用 Public API Key + 限流
21+
- `imgproxy`:对外提供签名处理 URL(可隐藏 origin URL)
22+
- 代理路由:为上游图片/接口选择代理
23+
24+
## 一键部署(Docker Compose,推荐)
25+
26+
前置:安装 Docker + Docker Compose。
27+
28+
1) 准备环境变量
29+
30+
```bash
31+
cp deploy/.env.example deploy/.env
32+
```
33+
34+
然后编辑 `deploy/.env`,至少建议修改:
35+
36+
- `SECRET_KEY`:JWT/API Key 哈希用(生产环境必须修改)
37+
- `ADMIN_PASSWORD`:后台密码(生产环境必须修改)
38+
- `FIELD_ENCRYPTION_KEY`:用于加密保存 refresh_token(生产环境必须提供;建议用 secret 挂载或文件方式)
39+
40+
2) 启动
41+
42+
```bash
43+
docker compose -f deploy/docker-compose.yml up -d --build
44+
```
45+
46+
3) 访问
47+
48+
- API 基址:`http://localhost:23222`
49+
- 健康检查:`GET http://localhost:23222/healthz`
50+
- 文档页:`GET http://localhost:23222/docs`
51+
- 后台 UI:`http://localhost:23222/admin`
52+
- Swagger:`http://localhost:23222/api/docs`
53+
54+
## 首次使用(导入数据 + 补全元数据)
55+
56+
这个项目不会“自动替你抓全站图片”,你需要先把图片记录导入数据库。
57+
58+
1) 登录后台
59+
60+
- 打开 `http://localhost:23222/admin`
61+
- 使用 `deploy/.env` 中的 `ADMIN_USERNAME` / `ADMIN_PASSWORD` 登录
62+
63+
2) 导入图片原图 URL
64+
65+
后台提供“导入”入口,支持:
66+
67+
- 直接粘贴多行文本(每行一个 URL)
68+
- 上传 `.txt` 文件(同样每行一个 URL)
69+
70+
导入内容应为 Pixiv 原图链接(例如 `i.pximg.net/.../img-original/...` 这类)。导入时会自动去重(按 illust_id + page)。
71+
72+
3) 配置 Pixiv refresh_token(可选,但强烈建议)
73+
74+
若你希望 Worker 自动补全/刷新元数据(tags、宽高、浏览/收藏/评论、R18 标记、AI 类型等),需要:
75+
76+
- 在后台添加一个或多个 refresh_token
77+
- 配置 `PIXIV_OAUTH_CLIENT_ID` / `PIXIV_OAUTH_CLIENT_SECRET`(以及可选的 `PIXIV_OAUTH_HASH_SECRET`
78+
79+
> 安全提示:refresh_token 属于敏感凭据;请只放在运行环境里(`deploy/.env` / secret 管理),不要写进代码/仓库。
80+
81+
4) 确认 Worker 正常
82+
83+
`/healthz` 会同时检查 DB、队列、以及 Worker 心跳;如果 `worker_ok=false`,通常意味着 Worker 没启动或无法连接数据库卷。
84+
85+
## 配置说明(节选)
86+
87+
所有配置均通过环境变量注入(见 `deploy/.env.example`):
88+
89+
- `APP_ENV``dev` / `prod``prod` 会启用更严格的必填校验)
90+
- `DATABASE_URL`:默认 SQLite(容器内 `/app/data/app.db`,通过 `../data:/app/data` 挂载)
91+
- `PUBLIC_API_KEY_REQUIRED` / `PUBLIC_API_KEY_RPM` / `PUBLIC_API_KEY_BURST`:公网访问保护(可选)
92+
- `WORKER_*``IMPORT_*``SQLITE_BUSY_TIMEOUT_MS`:Worker/导入/SQLite 运行参数
93+
- `IMGPROXY_*`:imgproxy 集成(可选)
94+
95+
## 本地开发(可选)
96+
97+
后端(Python 3.11):
98+
99+
```bash
100+
cd backend
101+
python -m venv .venv
102+
.\.venv\Scripts\activate
103+
python -m pip install -r ..\requirements-dev.txt
104+
alembic upgrade head
105+
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
106+
```
107+
108+
前端管理台(Node 20):
109+
110+
```bash
111+
cd frontend
112+
npm ci
113+
npm run dev
114+
```
115+
116+
如需让前端直连本地后端,设置 `VITE_API_BASE_URL`(例如 `http://localhost:8000`)。
117+
118+
## 运行测试
119+
120+
- 后端:`python -m pytest -q backend/tests`
121+
- 前端:`cd frontend && npm test`
122+

backend/Dockerfile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
FROM node:20-slim AS frontend-build
2+
3+
WORKDIR /frontend
4+
5+
COPY frontend/package.json frontend/package-lock.json /frontend/
6+
RUN npm ci --no-audit --no-fund
7+
8+
COPY frontend/ /frontend/
9+
RUN npm run build
10+
11+
12+
FROM python:3.11-slim
13+
14+
WORKDIR /app
15+
16+
ENV PYTHONDONTWRITEBYTECODE=1 \
17+
PYTHONUNBUFFERED=1
18+
19+
RUN python -m pip install --no-cache-dir --upgrade pip
20+
21+
COPY requirements.txt /app/requirements.txt
22+
RUN python -m pip install --no-cache-dir -r /app/requirements.txt
23+
24+
RUN mkdir -p /app/data /app/web
25+
26+
COPY backend/app /app/app
27+
COPY backend/alembic.ini /app/alembic.ini
28+
COPY backend/alembic /app/alembic
29+
COPY --from=frontend-build /frontend/dist /app/web/dist
30+
31+
EXPOSE 8000
32+
33+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

backend/alembic.ini

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[alembic]
2+
script_location = %(here)s/alembic
3+
prepend_sys_path = %(here)s
4+
sqlalchemy.url = sqlite:///./data/app.db
5+
6+
[loggers]
7+
keys = root,sqlalchemy,alembic
8+
9+
[handlers]
10+
keys = console
11+
12+
[formatters]
13+
keys = generic
14+
15+
[logger_root]
16+
level = WARN
17+
handlers = console
18+
19+
[logger_sqlalchemy]
20+
level = WARN
21+
handlers =
22+
qualname = sqlalchemy.engine
23+
24+
[logger_alembic]
25+
level = INFO
26+
handlers =
27+
qualname = alembic
28+
29+
[handler_console]
30+
class = StreamHandler
31+
args = (sys.stderr,)
32+
level = NOTSET
33+
formatter = generic
34+
35+
[formatter_generic]
36+
format = %(levelname)-5.5s [%(name)s] %(message)s
37+
datefmt = %H:%M:%S
38+

0 commit comments

Comments
 (0)