University Helper 帮助文档

DOCS · 晨读版

把它跑起来,然后去睡觉。

这里是 University Helper 的完整帮助:从本地起服务、配环境变量,到 Docker 部署和两个平台的功能用法。仓库内的 docs/ 目录始终是最权威的版本。

概览

University Helper 是一个自托管的校园课程自动化平台,基于 FastAPI + React 构建。它替你完成超星学习通的签到与泛雅课程任务、智慧树的课程任务, 并把所有任务状态保存在属于你自己的租户数据库里。

  • 多租户隔离 —— 每位用户一座 PostgreSQL 数据库(tenant_<username>),跨租户数据泄露在物理上不可能。
  • 凭据加密 —— 第三方平台账号密码使用 Fernet 对称加密后才写入数据库。
  • JWT 认证 —— REST API 全部走 Authorization: Bearer,令牌默认 30 分钟过期。
  • 加固部署 —— 非 root 容器、只读根文件系统、nginx 限速与安全响应头。

仓库名为 university-helper;部分源码仍保留历史内部名 easy_learning(容器名、环境变量前缀),正在逐步统一。

快速开始

一条龙引导脚本会创建 .env 并安装 Python / Node 依赖:

terminal
$ bash scripts/setup.sh        # 创建 .env,安装依赖
$ make start                   # docker-compose 栈(应用 + postgres)
$ make test                    # pytest + vitest

只跑后端

terminal
$ cd backend
$ cp .env.example .env         # 编辑 SECRET_KEY / CORS_ORIGINS / 数据库凭据
$ python -m venv .venv && source .venv/bin/activate
$ pip install -r requirements.txt -r requirements-dev.txt
$ uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

只跑前端

terminal
$ cd frontend
$ npm install
$ npm run dev          # http://localhost:3000,/api 自动代理到 :8000

数据库

需要 PostgreSQL 15+。database/ 下的 schema 文件会被 docker entrypoint 自动执行;Alembic 迁移位于 backend/alembic/versions/,用 alembic upgrade head 应用。

环境变量

后端启动前,至少要配置下面这些键(参考根目录 .env.example):

变量必填说明
MAIN_DB_HOST / NAME / USER / PASSWORD主库连接信息。
SECRET_KEYJWT 签名密钥,长度 ≥ 16 字符(生产建议 ≥ 32)。
CORS_ORIGINSJSON 数组,例如 ["http://localhost:3000"]
CREDENTIAL_ENCRYPTION_KEY生产必填Fernet 密钥(urlsafe-base64)。生产环境缺少它应用会拒绝启动;开发环境可省略。
POSTGRES_PASSWORDDocker 部署必填容器内 Postgres 超级用户密码。
APP_PORT后端监听端口,默认 8000
ENV设为 production 启用生产模式校验。
SHUAKE_COMPAT_SECRET≥ 32 字符时启用 7 天兼容令牌接口 GET /auth/shuake-token
DOCS_ENABLED设为 true 时在 /docs 暴露 Swagger UI。
生成 Fernet 密钥
$ python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
永远不要提交填好真实密钥的 .env。首次对外部署前,立即更换数据库密码与 JWT 密钥。

Docker 部署

生产部署使用 docker-compose.server.yml + Dockerfile.server, 由宿主机 nginx 负责 TLS 终止与前端静态文件(栈内没有 nginx 容器)。 权威文档见仓库内 docs/DEPLOYMENT.md

terminal
$ git clone https://github.com/sweetcornna/university-helper.git
$ cd university-helper
$ cp .env.example .env   # 填 SECRET_KEY · POSTGRES_PASSWORD · CREDENTIAL_ENCRYPTION_KEY · CORS_ORIGINS
$ docker compose -f docker-compose.server.yml -p university-helper up -d --build

首次部署的检查顺序:

  1. 手动创建并填好 .env(见上节,密钥不进仓库)。
  2. docker compose … up -d --build 起栈。
  3. 配置宿主机 nginx:TLS 终止、root frontend/dist;/api/ 反代到 http://127.0.0.1:8000
  4. 验证:curl -fsS http://127.0.0.1:8000/health
日常小改动用 scripts/hotfix_publish.sh 单文件热更新(SSH-key 认证优先),不要重复整栈重建。仓库根目录的旧 deploy.* 脚本已归档至 scripts/_legacy/,禁止运行。

功能指南 · 超星学习通

登录

在「超星」页面使用手机号 + 密码登录。登录成功后即可拉取课程列表,凭据按需加密保存。

签到

  • 普通 / 二维码 / 位置签到均支持;位置签到内置地图检索,搜索地点即可取得坐标。
  • 「一键全签」会对当前所有进行中的签到逐一提交(POST /chaoxing/sign-all)。

泛雅课程任务

在课程页选择要推进的课程后发起任务(POST /course/startplatform: "chaoxing")。 视频与章节测验会按章节顺序自动推进,进度与日志可随时查询,任务支持暂停 / 续跑 / 停止。

功能指南 · 智慧树

登录

  • 扫码登录:发起 POST /course/zhihuishu/qr-login 后页面会展示二维码,用智慧树 App 扫码确认。
  • 密码登录:手机号 + 密码(POST /course/zhihuishu/password-login)。

课程任务

选好课程后入队(POST /course/zhihuishu/tasks/course)。任务在后台逐节推进视频, 与超星任务共用同一套进度 / 日志 / 暂停 / 续跑 / 停止接口。

API 参考

Base URL:http://localhost:8000/api/v1(本地)。所有接口返回 JSON,错误统一为 { "code": "ErrorClassName", "message": "…" }。 除公共路由外,所有接口需要 Authorization: Bearer <jwt>

DOCS_ENABLED=true 后,/docs 有可交互的 Swagger UI,/openapi.json 是原始 spec —— 在线探索请优先用它们。

认证

方法路径用途
POST/auth/register注册:创建用户并自动建租户库,返回 JWT。用户名需匹配 ^[a-z0-9]+$;密码 ≥ 8 位且含大小写与数字。
POST/auth/login邮箱 + 密码登录,返回与注册相同的结构。
GET/auth/shuake-token签发 7 天兼容令牌(需配置 SHUAKE_COMPAT_SECRET)。

超星

方法路径用途
POST/chaoxing/login手机号 + 密码登录,预热客户端缓存。
GET/chaoxing/courses列出当前账号的课程。
POST/chaoxing/sign提交单个进行中的签到。
POST/chaoxing/sign-all提交所有进行中的签到。
GET/chaoxing/location/*地理编码 / 地点搜索 / 逆地理编码(公共路由,供地图选点)。

课程任务(超星泛雅 + 智慧树)

方法路径用途
POST/course/start启动课程任务,platform"chaoxing""zhihuishu"
GET/course/status/{task_id}轮询任务进度。
GET/course/tasks列出当前用户的任务。
GET/course/logs/{task_id}读取任务日志行。
POST/course/task/{task_id}/pause · /resume · /stop暂停 / 续跑 / 停止任务。
POST/course/zhihuishu/qr-login发起智慧树扫码登录,返回会话 id 与二维码 PNG。
POST/course/zhihuishu/password-login智慧树手机号 + 密码登录。
POST/course/zhihuishu/tasks/course入队智慧树课程任务。

轮询 statuslogs 时请带退避间隔;任务数据以 JSONB 存于你的租户库(course_task_store)。

常见问题

注册时提示用户名或密码不合法?

用户名只允许小写字母与数字(^[a-z0-9]+$);密码至少 8 位,且必须同时包含大写字母、小写字母和数字。

后端起不来,日志说缺环境变量?

检查 MAIN_DB_*SECRET_KEY(≥ 16 字符)、CORS_ORIGINS 是否齐全。ENV=production 时还必须提供 CREDENTIAL_ENCRYPTION_KEY,否则应用会拒绝启动 —— 这是有意设计。

前端请求 /api 报跨域或 404?

开发模式下 Vite 把 /api 代理到 http://localhost:8000,先确认后端在 8000 端口活着。跨域错误通常是 CORS_ORIGINS 没把前端地址(如 http://localhost:3000)加进去 —— 注意它是 JSON 数组格式。

课程任务的进度去哪里看?

界面上每个任务卡片都有实时进度;接口层面用 GET /course/status/{task_id} 轮询,GET /course/logs/{task_id} 看逐行日志。任务可随时 pause / resume / stop

Swagger / 接口调试页面在哪里?

设置 DOCS_ENABLED=true 后访问 /docs(Swagger UI),原始 OpenAPI spec 在 /openapi.json。生产环境建议保持关闭。

我的平台账号密码安全吗?

第三方平台凭据在写入数据库前先用 Fernet 对称加密,密钥只存在于服务器环境变量中,不进仓库、不进镜像。另外每位用户的数据存在独立的租户库里,应用层越权也读不到别人的数据。

8000 端口被占了怎么办?

.env 里的 APP_PORT,同时记得同步前端代理与 nginx 反代的上游端口。

怎么更新已部署的服务?

整体升级:拉新代码后重新 docker compose -f docker-compose.server.yml up -d --build。单文件热修复:scripts/hotfix_publish.sh backend/app/main.py(需要配置 SERVER_IP 与 SSH key),后端文件会同步进容器并自动重启,依赖层变更会触发整镜像重建。

安全与合规

安全基线

  • 后端容器非 root(UID/GID 10001)运行,只读根文件系统,Linux capabilities 全部裁剪。
  • nginx 强制 Content-Security-Policy、HSTS、frame-ancestors deny,登录接口限速 5 次/分。
  • Postgres 限制最大连接数、开启慢查询日志与 WAL 压缩;备份加密存储。
  • 安全漏洞请按 SECURITY.md 流程私下报告。

合规声明

请仅在符合学校规定、平台规则与当地法律的前提下使用本项目。 对第三方平台启用自动化之前,请自行评估风险与合规影响。本项目以 MIT 协议开源、自托管运行, 使用产生的一切后果由使用者自行承担。