Podcast: resume where you left off, synced between devices (shared progress store with audiobooks)
build-container / build (push) Successful in 9m26s
build-container / build (push) Successful in 9m26s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
aa2133ed9a
commit
b3494b9720
5 files changed
+61
-16
No files matched your search
@@ -1,5 +1,6 @@
|
||||
// Podcast proxy: only the allowed Podgrab calls get through, the Podgrab password is added server-side, audio ranges and redirects work.
|
||||
const http = require('http'), assert = require('assert');
|
||||
const http = require('http'), assert = require('assert'), fs = require('fs'), os = require('os'), path = require('path');
|
||||
process.env.DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'nehub-pod-'));
|
||||
const seen = [];
|
||||
const fake = http.createServer((req, res) => {
|
||||
let b = ''; req.on('data', c => b += c); req.on('end', () => {
|
||||
@@ -11,8 +12,8 @@ const fake = http.createServer((req, res) => {
|
||||
});
|
||||
}).listen(0, async () => {
|
||||
process.env.PODCAST_URL = 'http://127.0.0.1:' + fake.address().port + '/'; process.env.PODGRAB_PASSWORD = 'secret';
|
||||
const podcast = require('../podcast');
|
||||
const hub = http.createServer((req, res) => podcast.handle(req, res)).listen(0, async () => {
|
||||
const podcast = require('../podcast'), users = require('../users');
|
||||
const hub = http.createServer((req, res) => users.runAs({ id: 'pod-user', name: 'P' }, () => podcast.handle(req, res))).listen(0, async () => {
|
||||
const base = 'http://127.0.0.1:' + hub.address().port, get = (p, o = {}) => fetch(base + '/api/podcast' + p, { redirect: 'manual', ...o });
|
||||
try {
|
||||
let r = await get('/podcasts'); assert.equal(r.status, 200); assert.equal((await r.json())[0].Title, 'Show');
|
||||
@@ -20,6 +21,9 @@ const fake = http.createServer((req, res) => {
|
||||
r = await get('/podcastitems/e1/file', { headers: { range: 'bytes=0-3' } }); assert.equal(r.status, 206); assert.equal(await r.text(), 'abcd'); assert.equal(seen.at(-1).range, 'bytes=0-3');
|
||||
r = await get('/podcastitems/e2/file'); assert.equal(r.status, 302); assert.equal(r.headers.get('location'), 'https://cdn.example.com/a.mp3');
|
||||
r = await get('/podcasts', { method: 'POST', body: '{"url":"https://x.test/feed"}' }); assert.equal(r.status, 200); assert.equal(seen.at(-1).b, '{"url":"https://x.test/feed"}');
|
||||
const post = b => get('/progress', { method: 'POST', body: JSON.stringify(b) }).then(x => x.json());
|
||||
await post({ e1: { pos: 90, dur: 600, t: 10 } }); const pr = await post({ e1: { pos: 5, dur: 600, t: 3 }, e2: { pos: 7, dur: 300, t: 4 } });
|
||||
assert.equal(pr.e1.pos, 90, 'the newest position wins'); assert.equal((await (await get('/progress')).json()).e2.pos, 7);
|
||||
const n = seen.length;
|
||||
for (const [m, p] of [['GET', '/settings'], ['POST', '/settings'], ['GET', '/opml'], ['DELETE', '/tags/1'], ['GET', '/backups'], ['GET', '/podcasts/../settings'], ['DELETE', '/podcastitems/e1']]) {
|
||||
r = await get(p, { method: m }); assert.equal(r.status, 404, m + ' ' + p);
|
||||
|
||||
Reference in new issue
Block a user