Open Library in the book store; podcast topic search and transcript search; Recipes (Mealie) with a shopping list synced to Tasks; Contacts linked to Mail and the Calendar
build-container / build (push) Successful in 7m21s

- Store: Open Library search, books fetched from the Internet Archive (free editions only)
- Podcast: Podcast Index discovery by name and topic (optional key); search what is said across transcripts and play from that moment
- Recipes: browse, import from a link, add ingredients to Mealie's shopping list, mirrored two ways with a Shopping list in Tasks
- Contacts: per-person address book, vCard import/export, recipient suggestions in Mail, birthdays in the Calendar

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-26 08:55:32 -04:00
1 parent 0617664d97
commit 176b1b8169
28 files changed
+799 -46

No files matched your search

+2 -2
View File
@@ -48,7 +48,7 @@ async function lyrFromPlex(t) { // lyrics stored with the song (embedded, a .lrc
}
/** A transcript: the show's own if it publishes one, else (on request) one made on this server. Polls while that is being made. */
async function lyrSpoken(t, start) {
const q = new URLSearchParams({ key: t.key, src: t.src || '' });
const q = new URLSearchParams({ key: t.key, src: t.src || '', title: t.title || '', artist: t.artist || '', thumb: t.thumb || '' });
for (let n = 0; ; n++) { // (n restarts at -1 after an automatic start, so the POST goes out once)
if (!lyr.el || lyr.key !== t.key) return null;
let r; try { r = await jfetch('/api/transcript?' + q, start && n <= 0 ? { method: 'POST' } : undefined); } catch (e) { return { found: false, error: e.message }; }
@@ -168,7 +168,7 @@ pl.a.addEventListener('playing', async () => {
if (!t || !String(t.key).startsWith('pod:') || !t.src || lyrAsked.has(t.key) || !cfg.transcribe || lyrPref().noAuto) return;
lyrAsked.add(t.key);
try {
const q = new URLSearchParams({ key: t.key, src: t.src }), r = await jfetch('/api/transcript?' + q);
const q = new URLSearchParams({ key: t.key, src: t.src, title: t.title || '', artist: t.artist || '', thumb: t.thumb || '' }), r = await jfetch('/api/transcript?' + q);
if (r.state === 'none' && r.canTranscribe) await jfetch('/api/transcript?' + q, { method: 'POST' });
} catch { lyrAsked.delete(t.key); }
});