---
name: hottub
description: Work on the Hottub Rust server. Use this skill when you need the real build/run commands, compile-time single-provider builds, runtime env vars, API and proxy endpoint trigger examples, or yt-dlp verification steps for returned media URLs.
---

# Hottub

Hottub is a Rust `ntex` server. The main entrypoints are:

- `src/main.rs`: server startup, env loading, root redirect, `/api`, `/proxy`, static files
- `src/api.rs`: `/api/status`, `/api/videos`, `/api/test`, `/api/proxies`
- `src/proxy.rs`: `/proxy/...` redirect and media/image proxy routes
- `src/providers/mod.rs`: provider registry, compile-time provider selection, channel metadata
- `src/util/requester.rs`: outbound HTTP, Burp proxy support, FlareSolverr fallback

## Build and run

Default local run:

```bash
cargo run
```

Run with compiled-in debug logs:

```bash
cargo run --features debug
```

Compile a single-provider binary:

```bash
HOT_TUB_PROVIDER=hsex cargo build
```

Single-provider binary with debug logs:

```bash
HOT_TUB_PROVIDER=hsex cargo run --features debug
```

Notes:

- `HOT_TUB_PROVIDER` is the preferred compile-time selector.
- `HOTTUB_PROVIDER` is also supported as a fallback alias.
- Single-provider builds register only that provider at compile time, so other providers are not constructed and their init paths do not run.
- In a single-provider build, `/api/videos` requests with `"channel": "all"` are remapped to the compiled provider.
- The server binds to `0.0.0.0:18080`.

Useful checks:

```bash
cargo check -q
HOT_TUB_PROVIDER=hsex cargo check -q
HOT_TUB_PROVIDER=hsex cargo check -q --features debug
```

## Environment

Runtime env vars:

- `DATABASE_URL` required. SQLite path, for example `hottub.db`.
- `RUST_LOG` optional. Defaults to `warn` if unset.
- `PROXY` optional. Any value other than `"0"` enables proxy mode in the shared requester.
- `BURP_URL` optional. Outbound HTTP proxy used when `PROXY` is enabled.
- `FLARE_URL` optional but strongly recommended for provider work. Used for FlareSolverr fallback and some providers that call it directly.
- `DOMAIN` optional. Used for the `/` redirect target.
- `DISCORD_WEBHOOK` optional. Enables `/api/test` and provider error reporting to Discord.

Build-time env vars:

- `HOT_TUB_PROVIDER` optional. Compile only one provider into the binary.
- `HOTTUB_PROVIDER` optional fallback alias for the same purpose.

Practical `.env` baseline:

```dotenv
DATABASE_URL=hottub.db
RUST_LOG=info
PROXY=0
BURP_URL=http://127.0.0.1:8081
FLARE_URL=http://127.0.0.1:8191/v1
DOMAIN=127.0.0.1:18080
DISCORD_WEBHOOK=
```

## Endpoint surface

Root:

- `GET /`
  - Returns `302 Found`
  - Redirects to `hottub://source?url=<DOMAIN-or-request-host>`

Status API:

- `GET /api/status`
- `POST /api/status`
  - Returns the server status and channel list
  - The `User-Agent` matters because channel visibility can depend on parsed client version

Videos API:

- `POST /api/videos`
  - Main provider execution endpoint
  - Body is JSON matching `VideosRequest` in `src/videos.rs`

Diagnostics:

- `GET /api/test`
  - Sends a Discord test error if `DISCORD_WEBHOOK` is configured
- `GET /api/proxies`
  - Returns the current outbound proxy snapshot

Proxy endpoints:

- Redirect proxies:
  - `GET|POST /proxy/sxyprn/{endpoint}*`
  - `GET|POST /proxy/javtiful/{endpoint}*`
  - `GET|POST /proxy/spankbang/{endpoint}*`
  - `GET|POST /proxy/porndish/{endpoint}*`
  - `GET|POST /proxy/pimpbunny/{endpoint}*`
- Media/image proxies:
  - `GET|POST /proxy/noodlemagazine/{endpoint}*`
  - `GET|POST /proxy/noodlemagazine-thumb/{endpoint}*`
  - `GET|POST /proxy/hanime-cdn/{endpoint}*`
  - `GET|POST /proxy/hqporner-thumb/{endpoint}*`
  - `GET|POST /proxy/porndish-thumb/{endpoint}*`
  - `GET|POST /proxy/pimpbunny-thumb/{endpoint}*`

Everything else under `/` is served from `static/`.

## How to trigger endpoints

Verify the root redirect:

```bash
curl -i http://127.0.0.1:18080/
```

Fetch status with a Hot Tub-like user agent:

```bash
curl -s \
  -H 'User-Agent: Hot%20Tub/22c CFNetwork/1494.0.7 Darwin/23.4.0' \
  http://127.0.0.1:18080/api/status | jq
```

Equivalent `POST /api/status`:

```bash
curl -s -X POST http://127.0.0.1:18080/api/status | jq
```

Minimal videos request:

```bash
curl -s http://127.0.0.1:18080/api/videos \
  -H 'Content-Type: application/json' \
  -H 'User-Agent: Hot%20Tub/22c CFNetwork/1494.0.7 Darwin/23.4.0' \
  -d '{"channel":"hsex","sort":"date","page":1,"perPage":10}' | jq
```

Use `"all"` against a normal multi-provider build:

```bash
curl -s http://127.0.0.1:18080/api/videos \
  -H 'Content-Type: application/json' \
  -d '{"channel":"all","sort":"date","page":1,"perPage":10}' | jq
```

Use `"all"` against a single-provider build:

```bash
HOT_TUB_PROVIDER=hsex cargo run --features debug
curl -s http://127.0.0.1:18080/api/videos \
  -H 'Content-Type: application/json' \
  -d '{"channel":"all","sort":"date","page":1,"perPage":10}' | jq
```

Literal query behavior:

- Quoted queries are treated as literal substring filters after provider fetch.
- Leading `#` is stripped before matching.

Example:

```bash
curl -s http://127.0.0.1:18080/api/videos \
  -H 'Content-Type: application/json' \
  -d '{"channel":"hsex","query":"\"teacher\"","page":1,"perPage":10}' | jq
```

Trigger the Discord test route:

```bash
curl -i http://127.0.0.1:18080/api/test
```

Inspect proxy state:

```bash
curl -s http://127.0.0.1:18080/api/proxies | jq
```

Trigger a redirect proxy and inspect the `Location` header:

```bash
curl -I 'http://127.0.0.1:18080/proxy/spankbang/some/provider/path'
```

Trigger a media proxy directly:

```bash
curl -I 'http://127.0.0.1:18080/proxy/noodlemagazine/some/media/path'
```

## Videos request fields

Commonly useful request keys:

- `channel`
- `sort`
- `query`
- `page`
- `perPage`
- `featured`
- `category`
- `sites`
- `all_provider_sites`
- `filter`
- `language`
- `networks`
- `stars`
- `categories`
- `duration`
- `sexuality`

Most provider debugging only needs:

```json
{
  "channel": "hsex",
  "sort": "date",
  "query": null,
  "page": 1,
  "perPage": 10
}
```

## Recommended provider-debug workflow

1. Build only the provider you care about.
2. Run with `--features debug`.
3. Hit `/api/status` to confirm only the expected channel is present.
4. Hit `/api/videos` with either the provider id or `"all"`.
5. Inspect `.items[0].url`, `.items[0].formats`, `.items[0].thumb`, and any local `/proxy/...` URLs.
6. Verify the media URL with `yt-dlp`.

Example:

```bash
HOT_TUB_PROVIDER=hsex cargo run --features debug
curl -s http://127.0.0.1:18080/api/status | jq '.channels[].id'
curl -s http://127.0.0.1:18080/api/videos \
  -H 'Content-Type: application/json' \
  -d '{"channel":"all","page":1,"perPage":1}' | tee /tmp/hottub-video.json | jq
```

## yt-dlp verification

Use `yt-dlp` to prove that a returned video URL or format is actually consumable.

Check the primary item URL:

```bash
URL="$(jq -r '.items[0].url' /tmp/hottub-video.json)"
yt-dlp -v --simulate "$URL"
```

Prefer the first explicit format when present:

```bash
FORMAT_URL="$(jq -r '.items[0].formats[0].url' /tmp/hottub-video.json)"
yt-dlp -v -F "$FORMAT_URL"
yt-dlp -v --simulate "$FORMAT_URL"
```

If the format contains required HTTP headers, pass them through:

```bash
yt-dlp -v --simulate \
  --add-header 'Referer: https://example.com/' \
  --add-header 'User-Agent: Mozilla/5.0 ...' \
  "$FORMAT_URL"
```

If you want to build the command from JSON:

```bash
FORMAT_URL="$(jq -r '.items[0].formats[0].url' /tmp/hottub-video.json)"
mapfile -t HDRS < <(
  jq -r '.items[0].formats[0].http_headers // {} | to_entries[] | "--add-header=\(.key): \(.value)"' \
    /tmp/hottub-video.json
)
yt-dlp -v --simulate "${HDRS[@]}" "$FORMAT_URL"
```

For local proxy URLs returned by Hottub, verify the server endpoint directly:

```bash
LOCAL_URL="$(jq -r '.items[0].formats[0].url // .items[0].url' /tmp/hottub-video.json)"
yt-dlp -v --simulate "$LOCAL_URL"
```

## Interaction rules

- Prefer compile-time single-provider builds for provider work.
- Prefer `/api/status` before `/api/videos` so you know what channels the current binary exposes.
- When reproducing client-specific issues, send a realistic `User-Agent`.
- When debugging fetch failures, enable `debug` and set `FLARE_URL`.
- When debugging outbound request behavior, set `PROXY=1` and `BURP_URL=...`.
- Use `/api/test` only when you intentionally want a Discord notification.
