140 lines
9.9 KiB
Markdown
140 lines
9.9 KiB
Markdown
# Tadrisino API
|
||
|
||
بکاندِ **تدریسینو**، اپِ آموزشِ ریاضی به سبکِ دولینگو برای دانشآموزانِ پایهی سوم تا دوازدهم. دانشآموز روی نقشهای
|
||
از جزیرهها جلو میرود، هر جزیره آزمونی کوتاه از مسئلههای خودِ کتابِ درسی است، و هر جا گیر کند از دستیارِ هوشِ
|
||
مصنوعی میپرسد که جوابش را از همان کتاب میسازد.
|
||
|
||
این مخزن یک REST API روی Django است: برنامهی درسی و آزمون، پیشرفت و گیمیفیکیشن، دستیارِ مبتنی بر RAG، اشتراک
|
||
و پرداخت. فرانتاند مخزنِ جداگانهای است ([`Tadrisino/MathApp_frontend`](https://gitea.tadrisino2.ir/Tadrisino/MathApp_frontend)).
|
||
**قراردادِ میانِ دو طرف اسکیمای OpenAPIِ همین مخزن است**؛ هر تغییری در API از آنجا دیده میشود.
|
||
|
||
| | |
|
||
|---|---|
|
||
| **سرویسِ زنده** | `https://mathapi.tadrisino2.ir` · اپ: `https://math.tadrisino2.ir` |
|
||
| **فناوری** | Python 3.11 · Django 5.2 · Django REST Framework · PostgreSQL 14 · Redis · Qdrant · gunicorn پشتِ nginx و ArvanCloud |
|
||
| **API** | ۶۱ عملیات روی ۵۹ مسیر، مستند با OpenAPI (`/api/docs/`) |
|
||
| **محتوا** | ۱۰ پایه · ۵ کتاب · ۸۹ فصل · ۱٬۱۴۵ جزیره · ۵٬۴۰۶ درس · ۳۰٬۹۵۲ سوال |
|
||
| **تست** | ۹۷۳ تستِ خودکار، همه سبز |
|
||
| **سرویسهای بیرونی** | GapGPT (مدلِ زبانی) · Qdrant (جستجوی کتاب) · کاوهنگار (پیامک) · زرینپال و کافهبازار (پرداخت) |
|
||
|
||
---
|
||
|
||
## امکانات
|
||
|
||
| بخش | چه میکند |
|
||
|---|---|
|
||
| **ورود** | فقط با شمارهی موبایل و کدِ پیامکی؛ توکنِ دسترسیِ امضاشدهی یکساعته و توکنِ تمدید |
|
||
| **برنامهی درسی** | پایه ← کتاب ← فصل ← جزیره ← درس ← سوال؛ کلِ محتوا بهصورتِ JSONِ کامیتشده در `content/seed/` |
|
||
| **بازی** | آزمونِ هر جزیره، قفلِ ترتیبی، قلب، ستاره و امتیاز، زنجیرهی روزانه، جدولِ رتبهبندی، همراهها |
|
||
| **دستیار** | پاسخِ گامبهگام از روی همان کتاب (Qdrant + GapGPT)، فقط ریاضی، با شکلِ توصیفی که اپ میکشد |
|
||
| **اشتراک** | فصلِ اولِ هر کتاب رایگان؛ اشتراکِ یک/سه/ششماهه از زرینپال یا کافهبازار، با کدِ تخفیف و برنامهی معرفی |
|
||
| **پنلِ ادمین** | ویرایشِ محتوا، ورود و خروجِ فلهای سوال، پلنها، سفارشها (لغو و بازپرداخت)، تیکتها، گزارشهای کاربران |
|
||
| **پایش** | `/api/health` (دیتابیس، مهاجرت، کش، سرویسهای بیرونی، بکاپ)، لاگِ JSON برای هر درخواست، دفترِ رویدادِ پرداخت |
|
||
|
||
---
|
||
|
||
## شروعِ سریع
|
||
|
||
```bash
|
||
python3.11 -m venv venv && source venv/bin/activate
|
||
pip install -r requirements.txt
|
||
cp .env.example .env # برای توسعهی محلی DJANGO_DEBUG=1 را ست کنید
|
||
python manage.py migrate
|
||
python manage.py seed_content # برنامهی درسی و بانکِ سوال از content/seed/
|
||
python manage.py createsuperuser # برای /admin/
|
||
python manage.py runserver # http://127.0.0.1:8000
|
||
```
|
||
|
||
بدونِ `DB_NAME` در `.env` دیتابیسِ محلی SQLite است و نیازی به نصبِ Postgres نیست. `.env` خودکار خوانده میشود.
|
||
|
||
| آدرس | چیست |
|
||
|---|---|
|
||
| `/api/docs/` · `/api/redoc/` · `/api/schema/` | مستنداتِ زندهی API (روی سرور فقط با ورود به پنلِ ادمین) |
|
||
| `/admin/` | پنلِ ادمین |
|
||
| `/api/health` | سلامتِ سرویس |
|
||
|
||
**اولین درخواست:** با `DJANGO_DEBUG=1`، `POST /api/auth/otp/request` با یک شماره، سپس `POST /api/auth/login` با
|
||
کدی که در فیلدِ `devOtp` پاسخ آمده. `token` را در Swagger زیرِ **Authorize** بگذارید.
|
||
|
||
```bash
|
||
python manage.py test --noinput # کلِ تستها (سریال؛ --parallel روی macOS گیر میکند)
|
||
python manage.py test --noinput content # تستهای یک اپ
|
||
python manage.py spectacular --file schema.yaml --format openapi # خروجیِ قرارداد برای فرانت
|
||
```
|
||
|
||
برای استکِ لاگِ محلی (Loki و Grafana) [`docs/docker.md`](docs/docker.md) را ببینید.
|
||
|
||
---
|
||
|
||
## معماری
|
||
|
||
یک برنامهی جنگو در قالبِ «مونولیتِ ماژولار»: هر اپ یک مسئولیت دارد و مدلهای خودش را نگه میدارد.
|
||
|
||
| اپ | مسئولیت |
|
||
|---|---|
|
||
| `accounts` | هویت، ورود با کدِ پیامکی، نشست، پروفایل |
|
||
| `content` | کتابها، برنامهی درسی، درس، سوال، آزمونِ جزیره، بازخوردِ کاربر |
|
||
| `progress` | آمار، زنجیرهی روزانه، قلب، رتبهبندی، همراهها، گزارشِ هفتگی |
|
||
| `ai_tutor` · `rag` | دستیار: گفتگو، بازیابی از Qdrant، تولید با GapGPT، ورودِ کتاب |
|
||
| `subscription` · `payment` · `discount` · `affiliate` | پلن و اشتراک، سفارش و تراکنش، کدِ تخفیف، برنامهی معرفی |
|
||
| `notifications` · `support` · `campaigns` · `statuslog` | اعلان، پشتیبانی، کمپین، لاگِ تغییرِ وضعیت |
|
||
| `config` | تنظیمات، مسیرها، middleware، سلامت |
|
||
|
||
سه قاعده که از خواندنِ یک فایل پیدا نیست:
|
||
|
||
- **احرازِ هویت سیستمِ خودِ پروژه است.** `accounts.User` عمداً `AUTH_USER_MODEL` نیست؛ توکن با `django.core.signing`
|
||
امضا میشود (`accounts/authentication.py`). هدرِ نامعتبر یعنی درخواستِ ناشناس، و هر ویو خودش تصمیم میگیرد ورود
|
||
لازم است یا نه.
|
||
- **اپها با قرارداد جدا شدهاند، نه با ForeignKey.** ارجاعِ بینِ اپها با `user_id` یا `object_id` + `label` است تا
|
||
هر اپ بعداً جداشدنی بماند.
|
||
- **محدودیتِ نرخ متمرکز است.** هر اندپوینتِ حساس یک `throttle_scope` دارد و نرخش در `config/settings.py` است؛ IPِ
|
||
واقعی فقط از پروکسیهای ArvanCloud پذیرفته میشود.
|
||
|
||
شرحِ کامل و دلیلِ هر تصمیم در [`docs/architecture.md`](docs/architecture.md) و
|
||
[`docs/technical-handbook.md`](docs/technical-handbook.md) آمده است.
|
||
|
||
---
|
||
|
||
## استقرار
|
||
|
||
سرویس روی یک سرورِ مشترکِ شرکت اجرا میشود و مالِ این پروژه فقط پوشهی `~/mathapp-v2` و سرویسِ
|
||
`zareian-mathapp` است. کلِ انتشار:
|
||
|
||
```bash
|
||
ssh -t administrator@78.38.35.249 'cd ~/mathapp-v2 && ./deploy.sh; sudo systemctl restart zareian-mathapp'
|
||
```
|
||
|
||
`deploy.sh` کد را با `origin/main` یکی میکند، وابستگیها را نصب میکند، پیش از `migrate` از دیتابیس بکاپ میگیرد،
|
||
محتوا را seed و فایلهای استاتیک را جمع میکند و سلامتِ سرویس را میسنجد. سپس از بیرون:
|
||
|
||
```bash
|
||
curl https://mathapi.tadrisino2.ir/api/health # {"status": "ok"}
|
||
```
|
||
|
||
هر تغییرِ دیتابیس لحظهای به سرورِ بکاپِ جداگانهای میرود. رویهی کامل (متغیرهای محیطی، بکاپ و بازیابی، nginx،
|
||
عوض کردنِ دامنه، فروش در کافهبازار): [`docs/operations.md`](docs/operations.md).
|
||
|
||
---
|
||
|
||
## مستندات
|
||
|
||
| سند | موضوع |
|
||
|---|---|
|
||
| [`docs/technical-handbook.md`](docs/technical-handbook.md) · [PDF](docs/technical-handbook.pdf) | مستندِ فنیِ کامل برای تحویل و پیوستنِ توسعهدهندهی تازه |
|
||
| [`docs/architecture.md`](docs/architecture.md) | تصمیمهای معماری و دلیلشان |
|
||
| [`docs/operations.md`](docs/operations.md) | استقرار، پیکربندی، سلامت، بکاپ و بازیابی، nginx، پرداخت |
|
||
| [`docs/security-before-production.md`](docs/security-before-production.md) | آنچه پیش از کاربرِ واقعی باید بسته شود، و حفاظهای موجود |
|
||
| [`docs/content-authoring.md`](docs/content-authoring.md) | ویرایشِ محتوا از پنلِ ادمین و ساختِ انبوهِ سوال |
|
||
| [`docs/extraction-playbook.md`](docs/extraction-playbook.md) | خواندنِ کتابِ درسی با مدلِ تصویری، هزینه و انتخابِ مدل |
|
||
| [`docs/ai-cost-and-guardrails.md`](docs/ai-cost-and-guardrails.md) · [`docs/model-prices.md`](docs/model-prices.md) | هزینهی دستیار، حاشیهی سودِ اشتراکها، دفترِ قیمتِ مدلها |
|
||
| [`tools/loadtest/README.md`](tools/loadtest/README.md) | آزمونِ بار |
|
||
| [`CLAUDE.md`](CLAUDE.md) | راهنمای agentهای کدنویس، بهویژه قواعدِ کار روی سرورِ مشترک |
|
||
|
||
---
|
||
|
||
## وضعیت
|
||
|
||
سرویس زنده است و با حسابهای آزمونگر سنجیده میشود؛ هنوز به روی کاربرِ عمومی باز نشده. آنچه پیش از آن باید بسته
|
||
شود در [`docs/security-before-production.md`](docs/security-before-production.md) فهرست شده است. پرداختِ واقعی (زرینپال
|
||
و کافهبازار) تا انتهای مسیر هنوز آزموده نشده است.
|