chore: rename project from podpuddle to podsteadr

Renames the repo directory and every podpuddle/PODPUDDLE reference
across code, config, and docs to podsteadr/PODSTEADR (package names,
Docker Compose project/service/volume names, env var names, UI/RSS
strings). Existing Docker volume data (uploaded blobs, mediamtx
recordings, the server's sqlite DB and its nostr identity key) was
migrated to new podsteadr_-prefixed volumes with matching filenames
so it isn't orphaned by the rename.
This commit is contained in:
2026-07-25 01:11:42 +00:00
parent 26d166a7e8
commit 2d61abc40c
20 changed files with 49 additions and 49 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
# Hostname or IP your users will reach this box on (no scheme, no port) # Hostname or IP your users will reach this box on (no scheme, no port)
PUBLIC_HOST=localhost PUBLIC_HOST=localhost
# Where the podpuddle UI/API is reachable from browsers # Where the podsteadr UI/API is reachable from browsers
PUBLIC_URL=http://${PUBLIC_HOST}:8095 PUBLIC_URL=http://${PUBLIC_HOST}:8095
# Public endpoints handed out for streaming / playback / uploads # Public endpoints handed out for streaming / playback / uploads
+3 -3
View File
@@ -1,4 +1,4 @@
# podpuddle # podsteadr
Self-hosted, nostr-native podcast publishing and livestreaming. Self-hosted, nostr-native podcast publishing and livestreaming.
@@ -26,7 +26,7 @@ Then open http://localhost:8095, log in with a NIP-07 extension, and follow the
| Service | Host port | Purpose | | Service | Host port | Purpose |
|---|---|---| |---|---|---|
| podpuddle | 8095 | Web UI + API + RSS feeds | | podsteadr | 8095 | Web UI + API + RSS feeds |
| MediaMTX | 1935 | RTMP ingest (OBS) | | MediaMTX | 1935 | RTMP ingest (OBS) |
| MediaMTX | 8889 (+8189/udp) | WebRTC/WHIP ingest (browser) | | MediaMTX | 8889 (+8189/udp) | WebRTC/WHIP ingest (browser) |
| MediaMTX | 8890 | HLS playback | | MediaMTX | 8890 | HLS playback |
@@ -54,7 +54,7 @@ Tests: `cd server && npm test`.
## Data ## Data
Everything lives in named docker volumes: `podpuddle-data` (SQLite, server nostr key, Everything lives in named docker volumes: `podsteadr-data` (SQLite, server nostr key,
covers), `mediamtx-recordings` (stream recordings, 7-day retention), `blossom-data` covers), `mediamtx-recordings` (stream recordings, 7-day retention), `blossom-data`
(media blobs). `docker compose down` keeps them; `down -v` wipes them. (media blobs). `docker compose down` keeps them; `down -v` wipes them.
+1 -1
View File
@@ -1,4 +1,4 @@
# blossom-server (v4.x) configuration for podpuddle. # blossom-server (v4.x) configuration for podsteadr.
# Uploads require a signed nostr auth event (BUD-02, kind 24242); # Uploads require a signed nostr auth event (BUD-02, kind 24242);
# reads are public so podcast apps can fetch enclosures. # reads are public so podcast apps can fetch enclosures.
+7 -7
View File
@@ -1,9 +1,9 @@
name: podpuddle name: podsteadr
services: services:
podpuddle: podsteadr:
build: . build: .
container_name: podpuddle container_name: podsteadr
restart: unless-stopped restart: unless-stopped
ports: ports:
- "8095:8095" - "8095:8095"
@@ -21,7 +21,7 @@ services:
BLOSSOM_URL_INTERNAL: http://blossom:3000 BLOSSOM_URL_INTERNAL: http://blossom:3000
NOSTR_RELAYS: ${NOSTR_RELAYS:-wss://relay.damus.io,wss://nos.lol,wss://relay.nostr.band} NOSTR_RELAYS: ${NOSTR_RELAYS:-wss://relay.damus.io,wss://nos.lol,wss://relay.nostr.band}
volumes: volumes:
- podpuddle-data:/data - podsteadr-data:/data
- mediamtx-recordings:/recordings:ro - mediamtx-recordings:/recordings:ro
depends_on: depends_on:
- mediamtx - mediamtx
@@ -29,7 +29,7 @@ services:
mediamtx: mediamtx:
image: bluenviron/mediamtx:1.19.2 image: bluenviron/mediamtx:1.19.2
container_name: podpuddle-mediamtx container_name: podsteadr-mediamtx
restart: unless-stopped restart: unless-stopped
ports: ports:
- "1935:1935" # RTMP ingest - "1935:1935" # RTMP ingest
@@ -45,7 +45,7 @@ services:
blossom: blossom:
image: ghcr.io/hzrd149/blossom-server:4 image: ghcr.io/hzrd149/blossom-server:4
container_name: podpuddle-blossom container_name: podsteadr-blossom
restart: unless-stopped restart: unless-stopped
ports: ports:
- "8098:3000" - "8098:3000"
@@ -54,6 +54,6 @@ services:
- blossom-data:/app/data - blossom-data:/app/data
volumes: volumes:
podpuddle-data: podsteadr-data:
mediamtx-recordings: mediamtx-recordings:
blossom-data: blossom-data:
+13 -13
View File
@@ -1,4 +1,4 @@
# podpuddle — project status & handoff # podsteadr — project status & handoff
_Last updated: 2026-07-10. State: **working, verified end-to-end, parked.**_ _Last updated: 2026-07-10. State: **working, verified end-to-end, parked.**_
@@ -18,7 +18,7 @@ fully standalone compose stack today.
## How to resume ## How to resume
```sh ```sh
cd ~/podpuddle cd ~/podsteadr
docker compose up -d # data volumes were kept; everything resumes as-is docker compose up -d # data volumes were kept; everything resumes as-is
node scripts/e2e.mjs # 14 automated checks against the running stack node scripts/e2e.mjs # 14 automated checks against the running stack
``` ```
@@ -26,14 +26,14 @@ node scripts/e2e.mjs # 14 automated checks against the running stack
Open http://localhost:8095 and log in with a NIP-07 extension (Alby, nos2x). Open http://localhost:8095 and log in with a NIP-07 extension (Alby, nos2x).
For a non-localhost box, edit `.env` (`PUBLIC_HOST=…`) and `docker compose up -d --build`. For a non-localhost box, edit `.env` (`PUBLIC_HOST=…`) and `docker compose up -d --build`.
State that persists in the named volumes: `podpuddle-data` (SQLite DB, the State that persists in the named volumes: `podsteadr-data` (SQLite DB, the
server's nostr key in `config/server-nostr-key`, admin = first pubkey that ever server's nostr key in `config/server-nostr-key`, admin = first pubkey that ever
logged in), `blossom-data` (media blobs), `mediamtx-recordings` (stream logged in), `blossom-data` (media blobs), `mediamtx-recordings` (stream
recordings, 7-day retention). `docker compose down -v` wipes all of it. recordings, 7-day retention). `docker compose down -v` wipes all of it.
Note: the automated e2e run left test data behind (an "E2E Test Show" podcast Note: the automated e2e run left test data behind (an "E2E Test Show" podcast
with 2 episodes, test streams, and the e2e identity as **admin**). The e2e with 2 episodes, test streams, and the e2e identity as **admin**). The e2e
identity's secret key is in `/tmp/podpuddle-e2e-key` (hex). For real use you identity's secret key is in `/tmp/podsteadr-e2e-key` (hex). For real use you
probably want a clean slate: `docker compose down -v && docker compose up -d`, probably want a clean slate: `docker compose down -v && docker compose up -d`,
then log in with your own extension first so *your* pubkey becomes admin. then log in with your own extension first so *your* pubkey becomes admin.
@@ -43,9 +43,9 @@ Three containers on one compose network:
| Container | Image | Host ports | Role | | Container | Image | Host ports | Role |
|---|---|---|---| |---|---|---|---|
| `podpuddle` | built from `Dockerfile` (node:22 + ffmpeg) | 8095 | Fastify API + built Vue UI + RSS feeds | | `podsteadr` | built from `Dockerfile` (node:22 + ffmpeg) | 8095 | Fastify API + built Vue UI + RSS feeds |
| `podpuddle-mediamtx` | `bluenviron/mediamtx:1.19.2` | 1935 (RTMP), 8889 (WHIP), 8189/udp (ICE), 8890→8888 (HLS) | ingest + HLS output + recording | | `podsteadr-mediamtx` | `bluenviron/mediamtx:1.19.2` | 1935 (RTMP), 8889 (WHIP), 8189/udp (ICE), 8890→8888 (HLS) | ingest + HLS output + recording |
| `podpuddle-blossom` | `ghcr.io/hzrd149/blossom-server:4` (4.4.1) | 8098→3000 | sha256-addressed media blobs | | `podsteadr-blossom` | `ghcr.io/hzrd149/blossom-server:4` (4.4.1) | 8098→3000 | sha256-addressed media blobs |
Key flows: Key flows:
@@ -55,7 +55,7 @@ Key flows:
directly on any API route (scripting). First pubkey to log in becomes admin. directly on any API route (scripting). First pubkey to log in becomes admin.
- **Episode upload** — browser hashes the file (`crypto.subtle`, ≤2 GB), signs a - **Episode upload** — browser hashes the file (`crypto.subtle`, ≤2 GB), signs a
kind-24242 BUD-02 auth via NIP-07, PUTs **directly to blossom** (file never kind-24242 BUD-02 auth via NIP-07, PUTs **directly to blossom** (file never
transits podpuddle), then registers `{sha256, size, …}` with transits podsteadr), then registers `{sha256, size, …}` with
`POST /api/podcasts/:id/episodes`; server HEAD-verifies the blob before `POST /api/podcasts/:id/episodes`; server HEAD-verifies the blob before
accepting. Enclosure URL = `<blossom>/<sha256>.mp4`. accepting. Enclosure URL = `<blossom>/<sha256>.mp4`.
- **RSS** — `GET /feeds/:podcastId/feed.xml`, RSS 2.0 + itunes + podcast - **RSS** — `GET /feeds/:podcastId/feed.xml`, RSS 2.0 + itunes + podcast
@@ -68,7 +68,7 @@ Key flows:
travels as `?key=` (OBS stream key) or WHIP `Bearer`, is stored only as a travels as `?key=` (OBS stream key) or WHIP `Bearer`, is stored only as a
sha256 hash, and never appears in viewer URLs. MediaMTX delegates auth to sha256 hash, and never appears in viewer URLs. MediaMTX delegates auth to
`POST /api/mediamtx/auth` (2xx = allow); reads are public. `POST /api/mediamtx/auth` (2xx = allow); reads are public.
- **Status / NIP-53** — podpuddle polls the MediaMTX API (`:9997/v3/paths/list`, - **Status / NIP-53** — podsteadr polls the MediaMTX API (`:9997/v3/paths/list`,
every 3 s) and flips `planned → live → ended` (the stock MediaMTX image has no every 3 s) and flips `planned → live → ended` (the stock MediaMTX image has no
shell, so `runOn*` curl hooks are impossible — polling is deliberate). On each shell, so `runOn*` curl hooks are impossible — polling is deliberate). On each
transition it (re)publishes the kind-30311 live event **signed by the server's transition it (re)publishes the kind-30311 live event **signed by the server's
@@ -76,7 +76,7 @@ Key flows:
with the user `p`-tagged as `host`, to the relay list in Settings. 30311 is with the user `p`-tagged as `host`, to the relay list in Settings. 30311 is
replaceable, which is why the server key signs rather than the user's. replaceable, which is why the server key signs rather than the user's.
- **Recordings** — MediaMTX records fmp4 segments to the shared volume; - **Recordings** — MediaMTX records fmp4 segments to the shared volume;
podpuddle mounts it read-only, lists per-stream files, and podsteadr mounts it read-only, lists per-stream files, and
`POST /api/streams/:id/recordings/publish` remuxes (`ffmpeg -c copy `POST /api/streams/:id/recordings/publish` remuxes (`ffmpeg -c copy
+faststart`), uploads to blossom **with the server's key** (the only +faststart`), uploads to blossom **with the server's key** (the only
server-signed upload path), and creates the episode. server-signed upload path), and creates the episode.
@@ -112,7 +112,7 @@ frontend/ # Vue 3 + Vite + Tailwind + Pinia
admin claim, episode blob verification, feed ETag/304, stream key admin claim, episode blob verification, feed ETag/304, stream key
create/verify/rotate, webhook allow/deny paths, settings admin gating). create/verify/rotate, webhook allow/deny paths, settings admin gating).
- `node scripts/e2e.mjs` against the compose stack — **14/14**. - `node scripts/e2e.mjs` against the compose stack — **14/14**.
- Live leg (manual, via ffmpeg in the podpuddle container): - Live leg (manual, via ffmpeg in the podsteadr container):
- RTMP publish with the right key → HLS `index.m3u8` 200 (after MediaMTX's - RTMP publish with the right key → HLS `index.m3u8` 200 (after MediaMTX's
`?cookieCheck=1` redirect — use `curl -L`). `?cookieCheck=1` redirect — use `curl -L`).
- Wrong key → connection reset by MediaMTX (webhook denial confirmed live). - Wrong key → connection reset by MediaMTX (webhook denial confirmed live).
@@ -139,7 +139,7 @@ frontend/ # Vue 3 + Vite + Tailwind + Pinia
streaming/seeking is degraded. Options later: upgrade to the Deno rewrite, streaming/seeking is degraded. Options later: upgrade to the Deno rewrite,
or front blossom with nginx. or front blossom with nginx.
3. **Split-horizon blossom URL**: browsers use `http://<host>:8098`, but inside 3. **Split-horizon blossom URL**: browsers use `http://<host>:8098`, but inside
the podpuddle container that address doesn't exist. `BLOSSOM_URL_INTERNAL` the podsteadr container that address doesn't exist. `BLOSSOM_URL_INTERNAL`
(compose sets `http://blossom:3000`) is used server-side whenever the active (compose sets `http://blossom:3000`) is used server-side whenever the active
blossom URL equals the bundled default; feeds always carry the public URL. blossom URL equals the bundled default; feeds always carry the public URL.
4. **Stock MediaMTX image has no shell** — `runOnReady`-style hooks can't run 4. **Stock MediaMTX image has no shell** — `runOnReady`-style hooks can't run
@@ -154,7 +154,7 @@ frontend/ # Vue 3 + Vite + Tailwind + Pinia
## Remaining work ## Remaining work
- **Archipelago packaging** (the original deployment target, archy repo): - **Archipelago packaging** (the original deployment target, archy repo):
`apps/podpuddle/manifest.yml` + `apps/podpuddle-mediamtx` + `apps/podpuddle-blossom` `apps/podsteadr/manifest.yml` + `apps/podsteadr-mediamtx` + `apps/podsteadr-blossom`
following the `apps/btcpay-server` (dependencies) + `apps/monero-ui` following the `apps/btcpay-server` (dependencies) + `apps/monero-ui`
(`container.build` on `/opt/archipelago/docker/...`) patterns; bind volumes (`container.build` on `/opt/archipelago/docker/...`) patterns; bind volumes
under `/var/lib/archipelago/<app>`; add ports **8095, 1935, 8889, 8189/udp, under `/var/lib/archipelago/<app>`; add ports **8095, 1935, 8889, 8189/udp,
+1 -1
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>podpuddle</title> <title>podsteadr</title>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
+2 -2
View File
@@ -1,11 +1,11 @@
{ {
"name": "podpuddle-frontend", "name": "podsteadr-frontend",
"version": "0.1.0", "version": "0.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "podpuddle-frontend", "name": "podsteadr-frontend",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"hls.js": "^1.6.0", "hls.js": "^1.6.0",
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"name": "podpuddle-frontend", "name": "podsteadr-frontend",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"type": "module", "type": "module",
+1 -1
View File
@@ -16,7 +16,7 @@ async function logout() {
<header class="border-b border-slate-200 bg-white"> <header class="border-b border-slate-200 bg-white">
<div class="mx-auto flex max-w-4xl items-center justify-between px-4 py-3"> <div class="mx-auto flex max-w-4xl items-center justify-between px-4 py-3">
<RouterLink to="/" class="flex items-center gap-2 text-lg font-bold text-puddle-700"> <RouterLink to="/" class="flex items-center gap-2 text-lg font-bold text-puddle-700">
<span aria-hidden="true">💧</span> podpuddle <span aria-hidden="true">💧</span> podsteadr
</RouterLink> </RouterLink>
<nav v-if="auth.pubkey" class="flex items-center gap-4 text-sm"> <nav v-if="auth.pubkey" class="flex items-center gap-4 text-sm">
<RouterLink to="/" class="hover:text-puddle-600">Home</RouterLink> <RouterLink to="/" class="hover:text-puddle-600">Home</RouterLink>
+1 -1
View File
@@ -1,4 +1,4 @@
// Thin fetch wrapper for the podpuddle API (session cookie auth). // Thin fetch wrapper for the podsteadr API (session cookie auth).
export class ApiError extends Error { export class ApiError extends Error {
constructor(public status: number, message: string) { constructor(public status: number, message: string) {
+1 -1
View File
@@ -1,6 +1,6 @@
// Browser-direct Blossom (BUD-02) upload: hash locally, sign the kind-24242 // Browser-direct Blossom (BUD-02) upload: hash locally, sign the kind-24242
// authorization with the user's NIP-07 extension, PUT straight to the blossom // authorization with the user's NIP-07 extension, PUT straight to the blossom
// server. The file never transits podpuddle. // server. The file never transits podsteadr.
import { nip07 } from './nip07'; import { nip07 } from './nip07';
+1 -1
View File
@@ -27,7 +27,7 @@ async function login() {
<div class="mx-auto max-w-md"> <div class="mx-auto max-w-md">
<div class="card text-center"> <div class="card text-center">
<div class="mb-2 text-4xl" aria-hidden="true">💧</div> <div class="mb-2 text-4xl" aria-hidden="true">💧</div>
<h1 class="mb-1 text-2xl font-bold">podpuddle</h1> <h1 class="mb-1 text-2xl font-bold">podsteadr</h1>
<p class="mb-6 text-slate-500">Publish podcasts and go live on nostr, from your own server.</p> <p class="mb-6 text-slate-500">Publish podcasts and go live on nostr, from your own server.</p>
<template v-if="hasNip07()"> <template v-if="hasNip07()">
+4 -4
View File
@@ -1,6 +1,6 @@
# MediaMTX configuration for podpuddle. # MediaMTX configuration for podsteadr.
# Ingest: RTMP (OBS) + WebRTC/WHIP (browser). Output: HLS. Publish auth is # Ingest: RTMP (OBS) + WebRTC/WHIP (browser). Output: HLS. Publish auth is
# delegated to podpuddle via HTTP; stream status is polled from the API. # delegated to podsteadr via HTTP; stream status is polled from the API.
logLevel: info logLevel: info
@@ -9,7 +9,7 @@ apiAddress: :9997
# ---- authentication ------------------------------------------------------ # ---- authentication ------------------------------------------------------
authMethod: http authMethod: http
authHTTPAddress: http://podpuddle:8095/api/mediamtx/auth authHTTPAddress: http://podsteadr:8095/api/mediamtx/auth
authHTTPExclude: authHTTPExclude:
- action: api - action: api
- action: metrics - action: metrics
@@ -45,5 +45,5 @@ pathDefaults:
paths: paths:
# Streams live at live/<streamId>; publish requires the stream secret, # Streams live at live/<streamId>; publish requires the stream secret,
# which podpuddle checks in the auth webhook. # which podsteadr checks in the auth webhook.
"~^live/[A-Za-z0-9]+$": {} "~^live/[A-Za-z0-9]+$": {}
+3 -3
View File
@@ -10,12 +10,12 @@ import { createHash } from 'node:crypto';
import { existsSync, readFileSync, writeFileSync } from 'node:fs'; import { existsSync, readFileSync, writeFileSync } from 'node:fs';
import { finalizeEvent, generateSecretKey } from '../server/node_modules/nostr-tools/lib/esm/pure.js'; import { finalizeEvent, generateSecretKey } from '../server/node_modules/nostr-tools/lib/esm/pure.js';
const BASE = process.env.PODPUDDLE_URL ?? 'http://localhost:8095'; const BASE = process.env.PODSTEADR_URL ?? 'http://localhost:8095';
const BLOSSOM = process.env.BLOSSOM_URL ?? 'http://localhost:8098'; const BLOSSOM = process.env.BLOSSOM_URL ?? 'http://localhost:8098';
// Persist the test identity across runs — the first pubkey to log in becomes // Persist the test identity across runs — the first pubkey to log in becomes
// admin, so reruns must reuse it for the settings test to pass. // admin, so reruns must reuse it for the settings test to pass.
const KEY_FILE = '/tmp/podpuddle-e2e-key'; const KEY_FILE = '/tmp/podsteadr-e2e-key';
let sk; let sk;
if (existsSync(KEY_FILE)) { if (existsSync(KEY_FILE)) {
sk = Uint8Array.from(Buffer.from(readFileSync(KEY_FILE, 'utf8').trim(), 'hex')); sk = Uint8Array.from(Buffer.from(readFileSync(KEY_FILE, 'utf8').trim(), 'hex'));
@@ -89,7 +89,7 @@ ok('podcast created', podcast.status === 201 && podcast.json.id);
const podcastId = podcast.json.id; const podcastId = podcast.json.id;
// ---- blossom upload (BUD-02, signed like the browser would) ---- // ---- blossom upload (BUD-02, signed like the browser would) ----
const media = readFileSync(process.env.TEST_MP4 ?? '/tmp/podpuddle-test.mp4'); const media = readFileSync(process.env.TEST_MP4 ?? '/tmp/podsteadr-test.mp4');
const sha256 = createHash('sha256').update(media).digest('hex'); const sha256 = createHash('sha256').update(media).digest('hex');
const now = Math.floor(Date.now() / 1000); const now = Math.floor(Date.now() / 1000);
const auth24242 = finalizeEvent( const auth24242 = finalizeEvent(
+2 -2
View File
@@ -1,11 +1,11 @@
{ {
"name": "podpuddle-server", "name": "podsteadr-server",
"version": "0.1.0", "version": "0.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "podpuddle-server", "name": "podsteadr-server",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@fastify/cookie": "^11.0.2", "@fastify/cookie": "^11.0.2",
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"name": "podpuddle-server", "name": "podsteadr-server",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"type": "module", "type": "module",
+3 -3
View File
@@ -29,7 +29,7 @@ function nip98Header(url: string, method: string): string {
} }
beforeAll(async () => { beforeAll(async () => {
dataDir = mkdtempSync(join(tmpdir(), 'podpuddle-test-')); dataDir = mkdtempSync(join(tmpdir(), 'podsteadr-test-'));
const config = loadConfig({ const config = loadConfig({
DATA_DIR: dataDir, DATA_DIR: dataDir,
PUBLIC_URL: 'http://localhost:8095', PUBLIC_URL: 'http://localhost:8095',
@@ -59,7 +59,7 @@ describe('auth', () => {
expect(res.json().pubkey).toBe(pk); expect(res.json().pubkey).toBe(pk);
expect(res.json().isAdmin).toBe(true); // first login claims admin expect(res.json().isAdmin).toBe(true); // first login claims admin
const setCookie = res.headers['set-cookie'] as string; const setCookie = res.headers['set-cookie'] as string;
expect(setCookie).toContain('podpuddle_session='); expect(setCookie).toContain('podsteadr_session=');
cookie = setCookie.split(';')[0]; cookie = setCookie.split(';')[0];
}); });
@@ -168,7 +168,7 @@ describe('streams + mediamtx auth webhook', () => {
method: 'POST', method: 'POST',
url: '/api/streams', url: '/api/streams',
headers: { cookie }, headers: { cookie },
payload: { title: 'Live Test', summary: 'hi', hashtags: ['podpuddle'] }, payload: { title: 'Live Test', summary: 'hi', hashtags: ['podsteadr'] },
}); });
expect(res.statusCode).toBe(201); expect(res.statusCode).toBe(201);
const body = res.json(); const body = res.json();
+1 -1
View File
@@ -39,7 +39,7 @@ export interface BuildAppOptions {
export async function buildApp(opts: BuildAppOptions): Promise<FastifyInstance> { export async function buildApp(opts: BuildAppOptions): Promise<FastifyInstance> {
const { config } = opts; const { config } = opts;
const db = openDatabase(opts.dbPath ?? join(config.DATA_DIR, 'podpuddle.sqlite3')); const db = openDatabase(opts.dbPath ?? join(config.DATA_DIR, 'podsteadr.sqlite3'));
const settings = new SettingsService(db, config); const settings = new SettingsService(db, config);
const serverKey = loadServerKey(config.DATA_DIR); const serverKey = loadServerKey(config.DATA_DIR);
+1 -1
View File
@@ -5,7 +5,7 @@ import type { DB } from '../db/database.js';
import type { Config } from '../config.js'; import type { Config } from '../config.js';
import { Nip98Error, verifyNip98 } from '../services/nip98.js'; import { Nip98Error, verifyNip98 } from '../services/nip98.js';
export const SESSION_COOKIE = 'podpuddle_session'; export const SESSION_COOKIE = 'podsteadr_session';
declare module 'fastify' { declare module 'fastify' {
interface FastifyInstance { interface FastifyInstance {
+1 -1
View File
@@ -92,7 +92,7 @@ export function buildFeedXml(podcast: Podcast, episodes: Episode[], ctx: FeedCon
` <link>${xmlEscape(link)}</link>`, ` <link>${xmlEscape(link)}</link>`,
` <description>${xmlEscape(podcast.description)}</description>`, ` <description>${xmlEscape(podcast.description)}</description>`,
` <language>${xmlEscape(podcast.language)}</language>`, ` <language>${xmlEscape(podcast.language)}</language>`,
` <generator>podpuddle</generator>`, ` <generator>podsteadr</generator>`,
` <lastBuildDate>${rfc2822(lastPub)}</lastBuildDate>`, ` <lastBuildDate>${rfc2822(lastPub)}</lastBuildDate>`,
` <atom:link href="${xmlEscape(feedUrl)}" rel="self" type="application/rss+xml"/>`, ` <atom:link href="${xmlEscape(feedUrl)}" rel="self" type="application/rss+xml"/>`,
` <podcast:guid>${podcast.podcast_guid}</podcast:guid>`, ` <podcast:guid>${podcast.podcast_guid}</podcast:guid>`,