80 lines
3.4 KiB
Markdown
80 lines
3.4 KiB
Markdown
# ipx-play: shared episodes (#447)
|
|
|
|
When someone shares an episode in iPX, their server sends it to ipx-play, which keeps it and
|
|
answers with a short link, `https://play.ipxreader.app/e/<id>`. Anyone can open that link: it
|
|
shows the episode, plays it from the publisher's own file (from the time it was shared at, with
|
|
`?t=`), and offers to subscribe in the reader's own podcast app. Overcast's links are the model.
|
|
|
|
Only episodes of public feeds are sent, by the same rule that decides what the directory is sent:
|
|
nothing from a feed marked private, one with a login, one whose address carries a key, or one in
|
|
a private OPML. ipx-play refuses an address that looks like one too. Everything else is shared by
|
|
its own address, as before. ipx-play keeps what an episode is and where its file is; it serves no
|
|
file itself.
|
|
|
|
## Running it
|
|
|
|
A container of its own, `ipx-play`, in the Arcane project `ipx`, from its own image:
|
|
|
|
```sh
|
|
sh scripts/build-image.sh play
|
|
docker compose -f /mnt/fast/arcane/projects/ipx/compose.yaml pull ipx-play
|
|
docker compose -f /mnt/fast/arcane/projects/ipx/compose.yaml up -d ipx-play
|
|
```
|
|
|
|
The compose service, beside `ipx-directory`:
|
|
|
|
```yaml
|
|
ipx-play:
|
|
image: 192.168.1.130:5000/ipx-play:latest
|
|
container_name: ipx-play
|
|
restart: unless-stopped
|
|
env_file: play.env # PLAY_DATABASE_URL=postgres://...
|
|
environment:
|
|
PLAY_LOG_FORMAT: json
|
|
OTEL_EXPORTER_OTLP_ENDPOINT: http://192.168.1.130:4318 # Tempo is not on this network
|
|
volumes:
|
|
- /mnt/fast/appdata/ipx-play:/config
|
|
ports:
|
|
- "8102:8102"
|
|
```
|
|
|
|
Its config, `/mnt/fast/appdata/ipx-play/play.toml`:
|
|
|
|
```toml
|
|
bind = "0.0.0.0:8102"
|
|
public_url = "https://play.ipxreader.app"
|
|
|
|
# One for each ipx server allowed to make links; `ipx-play token <name>` prints the lines.
|
|
[[tokens]]
|
|
name = "tower"
|
|
token_sha256 = "..."
|
|
```
|
|
|
|
Tokens are read at start: after adding one, restart the container.
|
|
|
|
Its database is Postgres, `ipx_play` on the `databases` project's server, its URL in `play.env`
|
|
beside the compose file (mode 600), as the directory's is. It makes its one table, `shares`, on
|
|
start.
|
|
|
|
The tunnel publishes `play.ipxreader.app` to `http://192.168.1.130:8102` with no Access in front:
|
|
the pages are anyone's. cloudflared is not on the project's network, so not `ipx-play:8102`, as
|
|
the directory's route is the host's port too. `/v1` takes a token for everything.
|
|
|
|
## Setting up ipx
|
|
|
|
In Admin, Directory, Sharing episodes: the address ipx reaches it at, `http://ipx-play:8102`
|
|
inside Docker (the public address would go out through Cloudflare and back), and the token
|
|
`ipx-play token tower` printed. Without them Share hands over the episode's own address.
|
|
|
|
## The page
|
|
|
|
`/e/<id>` shows the show's art, its name, the episode's title, date and length, a player starting
|
|
at `?t=` (seconds, or `12:34`), the episode's own page if it has one, its notes (sanitized by
|
|
ammonia), and buttons that open Apple Podcasts, Overcast, Pocket Casts and Castro at the feed, with
|
|
the feed's address to paste into anything else. Open Graph tags give it a preview in Messages,
|
|
Slack and the like. It runs no script: the start time is the media fragment `#t=` on the file. Its
|
|
Content-Security-Policy lets it load only its stylesheet, the art and the file.
|
|
|
|
A show that inserts its ads per listener can move the time by an ad's length, as Overcast's links
|
|
can: the file is the publisher's, fetched fresh by each listener.
|