Codync
무료 오픈소스 1:1 대안, Grok Bot과 Muse 대신
저장소 정보는 아직 수집하지 않았습니다.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Python 3.13 and FastAPI power the API for https://www.podrapp.com/. The application
runs on Cloudflare Python Workers; a Python container supplies upstream egress for
iTunes and podcast RSS feeds, and parses feeds to JSON for /feed, which needs more
CPU than a Worker request allows.
Install Python 3.13, uv, Node.js 24 (used internally by pywrangler), and Docker (for the upstream proxy). Then:
uv sync --frozen
uv run pywrangler dev
For a standalone ASGI server without Cloudflare bindings or Docker:
uv run uvicorn podr.app:app --app-dir src --reload
Local ASGI mode uses bounded in-memory caching and direct upstream HTTP. Optional cloud features are disabled without bindings; Apple may reject direct requests. Use Wrangler to exercise production bindings and container egress.
The included devcontainer installs Python, uv, Node.js, GitHub CLI, and Docker client support. It reuses the host Docker daemon and persistent uv/npm cache volumes, so container rebuilds avoid reinstalling the toolchain and redownloading dependencies.
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run pywrangler deploy --dry-run --outdir=dist --containers-rollout=none
docker build -t podr-proxy .
The same commands are available as mise run check, mise run dev, mise run local,
and mise run container.
Base URL: https://podr-service.cascadiacollections.workers.dev
| Endpoint | Behavior |
|---|---|
GET / | Generated OpenAPI schema when q is absent |
GET /?q=python&limit=15 | Podcast search, limit 1–200 |
GET /?q=toppodcasts&limit=15&genre=1312 | Top podcasts, optional genre |
GET /podcast/42?summary=true | Metadata and recent episodes; optional RSS description |
GET /related?id=42&limit=10 | Genre-related podcasts, limit 1–20 |
GET /feed?rss_url=<feed>&count=300 | RSS 2.0 or Atom feed as JSON {status, feed, items}, newest first, count 1–300; parsed in the container, cached 30 minutes (longer if the feed's max-age says so, up to 24 hours) and revalidated with the feed's ETag/Last-Modified; weak ETag with If-None-Match → 304; feed.redirectedUrl appears when the feed moved permanently (301/308) |
GET /trending?limit=10&country=US | Seven-day trending queries, limit 1–50 |
GET /suggest?q=py&limit=5 | Prefix suggestions, limit 1–10 |
GET /semantic-search?q=python&limit=10 | Workers AI and Vectorize discovery |
GET /health | Liveness and circuit-breaker state |
GET /health/deep | Upstream probe through the container; 503 if unhealthy |
GET /openapi.json | Generated OpenAPI schema |
GET /docs, GET /redoc | Interactive API documentation |
Requests retain legacy integer-prefix parsing, clamping, plain-text errors, and GET-only behavior. Search responses retain provider fields. Health probes bypass rate limiting; other endpoints use 100 requests per minute per client IP when the binding is configured. Security and CORS headers are included on all responses.
src/podr/app.py: FastAPI routes, HTTP policy, generated documentation.src/podr/models.py: Pydantic response contracts.src/podr/validation.py: compatibility rules for query parameters.src/podr/services.py: iTunes, Podcast Index, RSS, related and semantic discovery.src/podr/cache.py: cache freshness, background revalidation, circuit breaker.src/podr/analytics.py: D1 aggregation, Analytics Engine metrics, R2 events.src/podr/runtime.py: native Python and Cloudflare binding adapters.src/entry.py: Workers ASGI entrypoint, daily cron and ITunesProxy Durable Object.container_src/main.py: streaming FastAPI/httpx upstream proxy.The Durable Object uses Cloudflare's low-level container API to manage readiness, port 8080, and five-minute idle shutdown in Python. Its class name, instance name, Worker name and migration history are preserved. No JavaScript application or Go proxy is required.
| Response | Fresh TTL |
|---|---|
| Search | 24 hours |
| Top podcasts | 2 hours |
| Podcast details and related | 4 hours |
| Semantic response | 1 hour |
| Trending and suggestions | 5 minutes |
| Root schema | 1 year, immutable |
Upstream cache entries retain an additional 24-hour stale window. Explicit storage timestamps determine freshness; stale responses trigger background refresh. Five upstream failures open the per-isolate circuit for 30 seconds. Stale entries can be served while the circuit is open. Analytics and cache writes use background work.
The daily 02:00 UTC cron warms the top ten D1 queries, or a fixed fallback list, using batches of five with 500 ms between batches.
wrangler.jsonc preserves the existing KV, R2, Analytics Engine, rate limiter,
Workers AI, and container bindings. D1 and Vectorize remain commented out until
provisioned. Set KV keys named flag:<name> to the literal string true:
| Flag | Behavior | Default |
|---|---|---|
trendingQueries | Enables trending and suggestions | false |
semanticSearch | Enables semantic search | false |
podcastSummaries | Enables requested RSS descriptions | false |
podcastIndex | Uses Podcast Index if both credentials exist | false |
enhancedCaching and analyticsExport were unused flags in the previous code.
R2 export continues whenever ANALYTICS_LAKE is configured, preserving actual
production behavior. R2 events contain query text; SHA-256 query hashes support D1
aggregation but do not anonymize its stored normalized queries.
Podcast Index credentials are Worker secrets:
uv run pywrangler secret put PODCAST_INDEX_KEY
uv run pywrangler secret put PODCAST_INDEX_SECRET
For D1, apply all migrations before enabling DB. Migration 0003 preserves old
rows and makes (query_hash, date, country) unique so country counts and atomic
upserts work. Empty country denotes global/unknown origin. Existing installations
must apply 0003 before deploying this Python version with DB enabled.
CI runs lint, formatting, tests, Worker dry-run packaging and a container build.
Successful CI for a push to main triggers deployment of that exact commit. Configure
CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID in GitHub secrets.
GitHub Actions is the only supported deploy path. Cloudflare's built-in Git
integration ("Workers Builds") must stay disconnected from this repository. It cannot
build the project: pywrangler vendors the Python dependencies into the Worker
bundle, so the npx wrangler deploy that Workers Builds runs by default cannot
produce a working deployment, and reproducing the real build there would duplicate
deploy.yml while skipping the CI gate that makes it safe. If a
Workers Builds: podr-service check reappears on pull requests, the repository has
been reconnected; disconnect it again under Workers & Pages > podr-service >
Settings > Build rather than trying to make that check pass.
uv run pywrangler deploy
Before the first production rollout, verify the Python Worker and container together in Wrangler/staging and measure CPU usage against the preserved 10 ms CPU budget. CPython contract tests do not validate Cloudflare's JavaScript FFI or actual Apple connectivity. For rollback, deploy the previous Git revision with its original Bun/TypeScript build and Go container.