# Development

Everything you need to run, build, and iterate on the addon locally.

---

## Prerequisites

- **Node.js 24+** (see `.node-version` / `.nvmrc`). Use [nvm](https://github.com/nvm-sh/nvm) or [fnm](https://github.com/Schniz/fnm) to pin the version.
- **An external torrent-search backend** reachable at a URL you control (required for piratebay/HiddenBay and PornRips catalogs). Without it, only directly-scraped sources (TorrentGalaxy, MagnetDL, LimeTorrents) will return results. Set the URL in `BACKEND_URL`.
- **Redis** (optional but recommended). Without Redis, catalog lists, covers, and metadata are not cached between requests, and the background enricher is disabled.

---

## Install Dependencies

```bash
cd /path/to/tpb-stremio-addon
npm install
```

---

## Environment Setup

Copy `.env.example` and fill in the values:

```bash
cp .env.example .env
# Edit .env:
#   BACKEND_URL=https://your-backend.example.com
#   REDIS_URL=redis://localhost:6379   (optional)
#   TPDB_API_KEY=...                   (optional)
#   STASHDB_API_KEY=...                (optional)
```

---

## Run Locally

```bash
# Production mode
npm start

# Development mode (Node --watch auto-reloads on file changes)
npm run dev
```

The server starts on port 7000 by default. Open the configure page:

```
http://localhost:7000/configure
```

To test a Stremio resource endpoint directly:

```bash
# Manifest (no user config - uses env vars only)
curl http://localhost:7000/manifest.json

# With a user config segment (base64url encoded)
curl http://localhost:7000/<config>/manifest.json
```

---

## Scripts

| Script | Command | Description |
|--------|---------|-------------|
| `start` | `node --max-old-space-size=512 src/index.js` | Start the server in production mode. Memory cap keeps it lean in constrained containers. |
| `dev` | `node --watch --max-old-space-size=512 src/index.js` | Start with `--watch` (Node 18+ built-in); automatically restarts when any `src/` file changes. |

---

## Docker

Build and run with Docker:

```bash
# Build the image
docker build -t stremio-tpb-porn .

# Run with environment variables
docker run -p 7000:7000 \
  -e BACKEND_URL=https://your-backend.example.com \
  -e REDIS_URL=redis://your-redis-host:6379 \
  -e TPDB_API_KEY=your-tpdb-key \
  stremio-tpb-porn
```

The container exposes port `7000` and includes a health check at `/health` (checked every 30 s).

The `Dockerfile` uses a multi-layer approach:
1. Install production-only dependencies (`npm install --omit=dev`).
2. Copy `src/` into the image.
3. Run `node src/index.js`.

The `railpack.toml` tells the build platform to use the Dockerfile rather than auto-detecting the runtime.

---

## Redis (optional)

Redis enables:
- Catalog list caching (30 min)
- Cover image caching (24 h)
- Debrid stream URL caching (4 h - per user + IP)
- Shared TPDB/StashDB metadata (30 d)
- Background metadata enrichment (requires Redis to write results)
- Cache warming background job

Without Redis, everything still works - it just re-fetches on every request.

To start a local Redis for development:

```bash
# Docker
docker run -p 6379:6379 redis:7-alpine

# Or with brew (macOS)
brew services start redis
```

Then set `REDIS_URL=redis://localhost:6379` in your `.env`.

---

## Testing Stremio Locally

Stremio can install addons from `localhost` URLs. In Stremio:

1. Open **Settings → Addons**.
2. Click **Install from URL** (or the search bar at the top of the Addons page).
3. Enter: `http://localhost:7000/manifest.json` (for the env-config install) or the `stremio://localhost:7000/…/manifest.json` URL generated by the configure page.

Stremio's desktop and web apps both support localhost addon installs.

---

## Inspecting Generated Config Segments

To decode a `{config}` URL segment and inspect what it contains:

```bash
# Replace <segment> with the base64url string from your install URL
node -e "
  const seg = '<segment>';
  const b64 = seg.replace(/-/g, '+').replace(/_/g, '/');
  console.log(JSON.parse(Buffer.from(b64, 'base64').toString()));
"
```

To encode a custom config for testing:

```bash
node -e "
  const cfg = { rdKey: 'test', maxResults: 10 };
  const seg = Buffer.from(JSON.stringify(cfg)).toString('base64')
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
  console.log(seg);
"
```

---

## Admin Endpoints

### Health Check

```bash
curl http://localhost:7000/health
# → { "status": "ok", "version": "...", "timestamp": "..." }
```

### Flush Catalog Cache

Requires `ADMIN_TOKEN` to be set:

```bash
curl -X POST http://localhost:7000/admin/flush-cat-cache \
  -H "X-Admin-Token: $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"backendUrl": "https://your-backend.example.com"}'
# → { "deleted": 12, "prefix": "https://your-backend.example.com" }
```

This deletes all `cat:v1:*` keys whose cache key starts with the given backend URL, forcing a fresh fetch on the next Stremio request. Useful when the backend returns empty results that get cached for 30 min.

---

## Project Layout

```
tpb-stremio-addon/
├── src/
│   ├── index.js              Entry point: Express app, routes, background jobs
│   ├── manifest.js           Dynamic manifest builder
│   ├── routes/
│   │   ├── catalog.js        Catalog resource handler
│   │   ├── meta.js           Meta resource handler
│   │   ├── stream.js         Stream resource handler
│   │   └── favorites.js      Favorites store API
│   ├── services/             External API clients (one per debrid provider + scrapers)
│   │   ├── realdebrid.js
│   │   ├── torbox.js
│   │   ├── premiumize.js
│   │   ├── easydebrid.js
│   │   ├── debridlink.js
│   │   ├── offcloud.js
│   │   ├── putio.js
│   │   ├── deepbrid.js
│   │   ├── linksnappy.js
│   │   ├── megadebrid.js
│   │   ├── debrider.js
│   │   ├── seedr.js
│   │   ├── hiddenbay.js      Cover image scraper
│   │   ├── backend.js        Torrent-search backend API client
│   │   ├── tpdb.js           ThePornDB metadata client
│   │   ├── stashdb.js        StashDB GraphQL metadata client
│   │   ├── referenceMeta.js  Reference addon fallback metadata
│   │   ├── hentai.js         Hentai reference addon proxy
│   │   ├── pornrips.js       PornRips detail-page resolver
│   │   ├── torrentgalaxy.js  TorrentGalaxy direct scraper
│   │   ├── magnetdl.js       MagnetDL direct scraper
│   │   └── limetorrents.js   LimeTorrents direct scraper
│   ├── jobs/
│   │   ├── cacheWarmer.js    Pre-warm catalog cache on startup
│   │   ├── referenceWarmer.js Pre-warm PornRips reference metadata
│   │   └── metaEnricher.js   Background TPDB/StashDB enrichment worker
│   └── utils/
│       ├── config.js         Config parsing, encoding, defaults
│       ├── cache.js          Redis-backed cache instances
│       ├── redis.js          Redis client wrapper
│       ├── debridProviders.js Provider registry
│       ├── adultSections.js  Catalog taxonomy definitions
│       ├── torrent.js        ID encoding, quality tags, magnet builder
│       ├── torrentCache.js   Torrent record get/set helpers
│       ├── metaMerge.js      TPDB + StashDB field-level merge
│       ├── pornripsCatalogs.js PornRips catalog utilities
│       ├── externalCatalogs.js Hentai catalog ID mapping
│       ├── externalGenres.json Genre lists for external sources
│       ├── rateLimit.js      express-rate-limit configuration
│       └── safeUrl.js        SSRF protection for operator-supplied URLs
├── public/
│   └── icon.svg              Addon icon served at /icon.svg
├── docs/                     Documentation (GitHub Pages site root)
├── Dockerfile
├── railpack.toml             Build platform config (use Dockerfile)
├── package.json
├── .env.example              Environment variable template
├── .node-version / .nvmrc    Node.js version pin (24)
└── LICENSE                   GNU GPL v3
```

---

## Dependencies

| Package | Purpose |
|---------|---------|
| `express` | HTTP server and routing |
| `axios` | HTTP client for all external API calls |
| `cheerio` | HTML parsing for direct scrapers and cover extraction |
| `express-rate-limit` | Per-IP rate limiting |
| `ioredis` | Redis client |
| `lru-cache` | Used internally by some cache utilities |

All dependencies are production-only (no dev dependencies declared). Node 24+ built-ins (`--watch`, `Buffer.from`, etc.) handle the development workflow.
