- backend: FastAPI + SQLAlchemy 2.0(async) + asyncpg + Alembic - 7 API routes: auth/me/articles/sources/bookmarks/subscriptions/admin - models: User/Source/Article/Bookmark/Subscription/ApiToken - services: RSS fetcher (feedparser) + Tencent TMT translator with quota + cache + local NLLB fallback - workers: APScheduler + asyncio pipeline (fetch -> dedupe -> insert -> translate) - seed scripts: create_user, seed_sources (5 RSS: Reuters/BBC/Al Jazeera/NHK/DW) - frontend: Vue 3 + Vite + Naive UI + Pinia + vue-router - pages: Login, Feed (24h), ArticleDetail, Sources, Bookmarks, AdminSources - deploy: docker-compose (postgres/redis/api/worker/frontend/caddy) - docs: README, DEPLOY, architecture, acceptance
73 lines
1.6 KiB
TOML
73 lines
1.6 KiB
TOML
[project]
|
|
name = "news-aggregator"
|
|
version = "0.1.0"
|
|
description = "Private news aggregator with multi-source RSS, translation, web + Android clients"
|
|
requires-python = ">=3.12"
|
|
dependencies = [
|
|
# web
|
|
"fastapi>=0.115.0",
|
|
"uvicorn[standard]>=0.32.0",
|
|
"pydantic>=2.9.0",
|
|
"pydantic-settings>=2.6.0",
|
|
"python-multipart>=0.0.12",
|
|
# db
|
|
"sqlalchemy[asyncio]>=2.0.36",
|
|
"asyncpg>=0.30.0",
|
|
"alembic>=1.14.0",
|
|
"psycopg2-binary>=2.9.10", # alembic sync driver
|
|
# cache / queue
|
|
"redis>=5.2.0",
|
|
# auth
|
|
"passlib[bcrypt]>=1.7.4",
|
|
"bcrypt==4.0.1", # 锁版本,passlib 与新版 bcrypt 不兼容
|
|
"pyjwt>=2.10.0",
|
|
# fetch / parse
|
|
"feedparser>=6.0.11",
|
|
"httpx>=0.28.0",
|
|
"trafilatura>=2.0.0",
|
|
"beautifulsoup4>=4.12.3",
|
|
"lxml>=5.3.0",
|
|
"python-dateutil>=2.9.0",
|
|
# translation
|
|
"tencentcloud-sdk-python>=3.0.1200",
|
|
# scheduling
|
|
"apscheduler>=3.10.4",
|
|
# observability
|
|
"structlog>=24.4.0",
|
|
"orjson>=3.10.10",
|
|
# util
|
|
"pydantic-extra-types>=2.10.0",
|
|
"email-validator>=2.2.0",
|
|
"python-slugify>=8.0.4",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
dev = [
|
|
"pytest>=8.3.0",
|
|
"pytest-asyncio>=0.24.0",
|
|
"ruff>=0.7.0",
|
|
"mypy>=1.13.0",
|
|
]
|
|
|
|
[tool.ruff]
|
|
line-length = 110
|
|
target-version = "py312"
|
|
|
|
[tool.ruff.lint]
|
|
select = ["E", "F", "I", "B", "UP", "W"]
|
|
ignore = ["E501"]
|
|
|
|
[tool.mypy]
|
|
python_version = "3.12"
|
|
ignore_missing_imports = true
|
|
strict_optional = true
|
|
warn_unused_ignores = true
|
|
|
|
[build-system]
|
|
requires = ["setuptools>=68"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[tool.setuptools.packages.find]
|
|
where = ["."]
|
|
include = ["app*"]
|