Paid episodes: - server/services/cashu.ts: self-custodied Cashu wallet against a configured mint (NUT-04 mint quote -> bolt11 invoice -> mint/store proofs -> LNURL-pay payout on withdraw). Buyers pay a plain Lightning invoice, no Cashu wallet needed on their end. - routes/marketplace.ts: purchase/confirm flow, download-url paywall gate, reseller certification/revocation, earnings ledger + withdraw. - services/marketplace.ts: producer + certified-reseller source resolution, with a naive per-seller sales-count reputation signal. Discovery: - services/rss.ts: <podsteadr:source> RSS tag on priced episodes (producer + resellers, price, sales count, url) so pricing/sources are discoverable straight from the feed, not just a separate API call. Locked episodes point their <enclosure> at an info page instead of the raw file. - routes/feeds.ts: /catalog.opml lists every podcast this instance hosts, for peer podsteadr servers or any OPML-aware crawler to discover without a central directory. Frontend: episode wizard price/reseller controls, sources display, earnings dashboard. Also fixes CORS and a container-image reference: - app.ts: register @fastify/cors, open on the catalog/feed/sources endpoints (already deliberately public/crawlable) and on purchase/confirm (already accept stateless NIP-98 header auth for exactly this case). Credentials stay off, so the session cookie never crosses origins — cookie-authed admin routes stay same-origin-only. Needed so external clients like podsteadr-player can browse/buy/play from a different origin. - docker-compose.yml: fully qualify the mediamtx image reference (docker.io/bluenviron/mediamtx:1.19.2) — some Podman hosts have no unqualified-search registry configured and fail to resolve short names. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
61 lines
1.9 KiB
YAML
61 lines
1.9 KiB
YAML
name: podsteadr
|
|
|
|
services:
|
|
podsteadr:
|
|
build: .
|
|
container_name: podsteadr
|
|
restart: unless-stopped
|
|
ports:
|
|
- "8095:8095"
|
|
environment:
|
|
NODE_ENV: production
|
|
PORT: "8095"
|
|
DATA_DIR: /data
|
|
RECORDINGS_DIR: /recordings
|
|
PUBLIC_URL: ${PUBLIC_URL:-http://localhost:8095}
|
|
MEDIAMTX_API_URL: http://mediamtx:9997
|
|
MEDIAMTX_RTMP_PUBLIC: ${MEDIAMTX_RTMP_PUBLIC:-rtmp://localhost:1935}
|
|
MEDIAMTX_WHIP_PUBLIC: ${MEDIAMTX_WHIP_PUBLIC:-http://localhost:8889}
|
|
MEDIAMTX_HLS_PUBLIC: ${MEDIAMTX_HLS_PUBLIC:-http://localhost:8890}
|
|
BLOSSOM_URL_DEFAULT: ${BLOSSOM_URL_DEFAULT:-http://localhost:8098}
|
|
BLOSSOM_URL_INTERNAL: http://blossom:3000
|
|
NOSTR_RELAYS: ${NOSTR_RELAYS:-wss://relay.damus.io,wss://nos.lol,wss://relay.nostr.band}
|
|
CASHU_MINT_URL_DEFAULT: ${CASHU_MINT_URL_DEFAULT:-https://mint.minibits.cash/Bitcoin}
|
|
volumes:
|
|
- podsteadr-data:/data
|
|
- mediamtx-recordings:/recordings:ro
|
|
depends_on:
|
|
- mediamtx
|
|
- blossom
|
|
|
|
mediamtx:
|
|
image: docker.io/bluenviron/mediamtx:1.19.2
|
|
container_name: podsteadr-mediamtx
|
|
restart: unless-stopped
|
|
ports:
|
|
- "1935:1935" # RTMP ingest
|
|
- "8889:8889" # WebRTC / WHIP
|
|
- "8189:8189/udp" # WebRTC ICE
|
|
- "8890:8888" # HLS (host 8890; 8888 kept free for other apps)
|
|
environment:
|
|
# Browsers need a reachable ICE host candidate; set PUBLIC_HOST in .env
|
|
MTX_WEBRTCADDITIONALHOSTS: ${PUBLIC_HOST:-localhost}
|
|
volumes:
|
|
- ./mediamtx/mediamtx.yml:/mediamtx.yml:ro
|
|
- mediamtx-recordings:/recordings
|
|
|
|
blossom:
|
|
image: ghcr.io/hzrd149/blossom-server:4
|
|
container_name: podsteadr-blossom
|
|
restart: unless-stopped
|
|
ports:
|
|
- "8098:3000"
|
|
volumes:
|
|
- ./blossom/config.yml:/app/config.yml:ro
|
|
- blossom-data:/app/data
|
|
|
|
volumes:
|
|
podsteadr-data:
|
|
mediamtx-recordings:
|
|
blossom-data:
|