{"id":30456237,"url":"https://github.com/mooshieblob1/anime-tracker","last_synced_at":"2025-08-23T16:13:22.307Z","repository":{"id":310012801,"uuid":"1038380199","full_name":"Mooshieblob1/anime-tracker","owner":"Mooshieblob1","description":null,"archived":false,"fork":false,"pushed_at":"2025-08-15T05:13:43.000Z","size":27,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-15T07:05:54.678Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Mooshieblob1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-15T05:03:29.000Z","updated_at":"2025-08-15T05:13:46.000Z","dependencies_parsed_at":"2025-08-15T07:05:56.154Z","dependency_job_id":"01808e45-097c-4cf2-ae6c-7ed60571057c","html_url":"https://github.com/Mooshieblob1/anime-tracker","commit_stats":null,"previous_names":["mooshieblob1/anime-tracker"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/Mooshieblob1/anime-tracker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mooshieblob1%2Fanime-tracker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mooshieblob1%2Fanime-tracker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mooshieblob1%2Fanime-tracker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mooshieblob1%2Fanime-tracker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Mooshieblob1","download_url":"https://codeload.github.com/Mooshieblob1/anime-tracker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mooshieblob1%2Fanime-tracker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271755455,"owners_count":24815411,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-23T02:00:09.327Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-23T16:13:19.185Z","updated_at":"2025-08-23T16:13:22.296Z","avatar_url":"https://github.com/Mooshieblob1.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Anime \u0026 Manga Tracker (MVP)\n\nA small FastAPI app for tracking manga/anime progress. It uses JWT auth, persists your library in SQLite via SQLModel, integrates with AniList for OAuth import and search, and ships with a minimal static frontend served by FastAPI.\n\n## What’s included\n- Auth: password login (built-in demo user) with JWT bearer tokens\n- Persistence: SQLite database (`app.db`) with SQLModel; items survive restarts\n- Library: add/list/get/update/delete items; status and progress fields; summary endpoint\n- Sources:\n  - Hardcoded sources list and mock search\n  - Autocomplete powered by AniList GraphQL (no OAuth required)\n  - “Max” episodes/chapters lookup per title\n- AniList OAuth: connect/import your lists (tokens stored in-memory per user for MVP)\n- Frontend: single static page served from `/`\n- Tests: API tests for health, auth+library CRUD, and sources\n\n## Quickstart\n\n1) Create venv and install deps\n```bash\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\n```\n\n2) Run the server\n```bash\nuvicorn app.main:app --reload\n```\n- App + Frontend: http://127.0.0.1:8000\n- API docs: http://127.0.0.1:8000/docs\n\n3) Sign in\n- Demo user: `demo` / `demo1234`\n- Or register via the Register button in the login modal (POST `/api/auth/register`).\n\n4) Use it\n- Search: start typing in the “Search title…” box; pick a suggestion (max chapters/episodes will show)\n- Add: set type, optional progress, and click Add to save to your library\n- Edit: change status (Planning, Reading/Watching, Dropped, Completed) and adjust progress inline; Save\n- Remove: click Remove on an item\n- AniList (optional):\n  - Click “Add AniList account” after logging in; authorize in the popup\n  - “Import from AniList” to pull your lists into the library\n\n## API overview\n- Auth\n  - POST `/api/auth/token` (OAuth2 password form) → JWT\n  - POST `/api/auth/register` → create a user\n  - GET `/api/auth/me` → current user\n- Library\n  - GET `/api/library/items` → list\n  - POST `/api/library/items` → create `{title, type, source, cover_url?, status?, progress?}`\n  - GET `/api/library/items/{id}` → read\n  - PATCH `/api/library/items/{id}` → update `{status?, progress?}`\n  - DELETE `/api/library/items/{id}` → delete\n  - GET `/api/library/summary` → simple counts\n- Sources\n  - GET `/api/sources/` → hardcoded sources\n  - GET `/api/sources/search?q=\u0026type=` → mock search (tests)\n  - GET `/api/sources/autocomplete?q=\u0026type=` → AniList-backed suggestions\n  - GET `/api/sources/max?q=\u0026type=` → max episodes/chapters for a title\n- AniList\n  - GET `/api/anilist/connect-url` → begin OAuth\n  - GET `/api/anilist/callback` → OAuth redirect (server endpoint)\n  - GET `/api/anilist/status` → connected?\n  - POST `/api/anilist/import` → import lists (requires OAuth)\n\n\u003c!-- Configuration section intentionally omitted for MVP simplicity. Autocomplete and max lookups don’t require OAuth; AniList import is optional. --\u003e\n\n## Dev and tests\n- DB is auto-initialized on startup.\n- When running tests, a separate `app_test.db` is used automatically.\n- Run tests:\n```bash\npytest -q\n```\n\n## Implementation notes\n- Tokens for AniList OAuth are stored in-memory keyed by username (MVP only).\n- Datetimes are stored as UTC.\n- CORS is permissive for the MVP; tighten for production.\n\n## Roadmap\n\nBelow are proposed next steps that are not yet implemented. Each item includes a brief methodology to reach the milestone.\n\n1) Persist “max” chapter/episode values in the DB\n   - Goal: Show consistent “progress X of N” without re-querying AniList every time and support offline viewing.\n   - Methodology:\n     - Schema: add `max_progress: int | None` to `LibraryItem` (nullable). Create an Alembic migration.\n     - Write path: on add via autocomplete, include the fetched max in the POST payload; store it.\n     - Backfill: add a one-off admin endpoint/script to query AniList and populate `max_progress` for existing rows.\n     - UI: always render “of N” from DB when present; allow manual override.\n     - Tests: unit test create/update, and a backfill script test with mocked AniList.\n\n2) Store AniList media IDs and enrich metadata\n   - Goal: Link items to canonical AniList entries for better accuracy and future sync.\n   - Methodology:\n     - Schema: add `anilist_id: int | None` and optional fields like `format`, `site_url`.\n     - Create: when selecting from autocomplete, save the `anilist_id` along with title/cover.\n     - Enrich: add an endpoint to refresh metadata for an item (cover/title/format) from AniList.\n     - Tests: ensure ID persists and enrichment updates fields safely.\n\n3) Two-way AniList sync (statuses and progress)\n   - Goal: Keep local library and AniList in sync (import + push updates).\n   - Methodology:\n     - OAuth: persist AniList tokens securely (DB table) and implement refresh-token handling.\n     - Mapping: define status/progress mapping between local and AniList (Reading↔CURRENT, Completed↔COMPLETED, Dropped↔DROPPED, Planning↔PLANNING; episodes/chapters to progress).\n     - Push: on local PATCH, enqueue a job to update AniList via GraphQL mutation for linked `anilist_id`.\n     - Pull: extend import to upsert by `anilist_id`; add a “Sync now” endpoint to fetch updates.\n     - Background: add a simple task runner or APScheduler for periodic sync; handle retries/backoff.\n     - Conflict: last-write-wins with a `synced_at` timestamp; surface conflicts in logs.\n     - Tests: mock GraphQL; verify both push and pull paths.\n\n4) Caching and rate-limit handling for AniList queries\n   - Goal: Reduce latency and avoid rate-limit hits.\n   - Methodology:\n     - Add a small cache (SQLite table or in-memory with TTL) keyed by query and variables.\n     - Respect AniList error codes; implement exponential backoff and minimal retry.\n     - Log cache hit/miss metrics; expose debug stats endpoint.\n     - Tests: cache TTL and backoff behavior with mocked time.\n\n5) Additional source integrations (e.g., MangaDex)\n   - Goal: Search and add from non-AniList sources.\n   - Methodology:\n     - Create `app/services/mangadex.py` with thin search/details functions.\n     - Add `/api/sources/mangadex/search` and corresponding frontend wiring.\n     - Normalize result shape to current autocomplete model; store `source` accordingly.\n     - Tests: mock search results; verify add flow.\n\n6) UX improvements for the library\n   - Goal: Faster updates and better browsing.\n   - Methodology:\n     - Increment/decrement buttons next to progress; optional keyboard shortcuts.\n     - Filters (type/status) and sort (updated_at, title); pagination for large libraries.\n     - Toast notifications for save/remove; loading indicators for autocomplete.\n     - Tests: basic UI smoke via Playwright (optional) or DOM checks in unit tests.\n\n7) User management enhancements\n   - Goal: Improve beyond the demo.\n   - Methodology:\n     - Registration refinements and basic profile editing.\n     - Password reset flow (token email mock or local code entry for dev environments).\n     - Tests: auth flows and edge cases.\n\n8) Migrations with Alembic\n   - Goal: Safely evolve the schema.\n   - Methodology:\n     - Initialize Alembic; configure SQLModel metadata target.\n     - Generate migration for `max_progress` and `anilist_id` changes.\n     - Document migration commands; add a small helper script to apply on startup in dev.\n     - Tests: migration up/down on a temp DB.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmooshieblob1%2Fanime-tracker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmooshieblob1%2Fanime-tracker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmooshieblob1%2Fanime-tracker/lists"}