Build and Push Docker Image / build-and-push (push) Successful in 6m47s
- Admin: sign-up Open / Invite only / Closed with single-use invite links - Present mode for scripts (auto-scroll) and outlines (step through, pace vs planned minutes) - Series: group studies on the dashboard, filter by series, calendar file for a study's sessions - Lesson handout: printable page per session (passage, outline, questions, writing lines) - Save a chunk's notes as your own study template (synced) - Voice dictation for notes and scripts (browser speech recognition) - Reading progress: map of the 66 books and a calendar of days read, synced and merged across devices - Export highlights and bookmarks as Markdown or Word, grouped by named colour - Verse of the day push to the ntfy topic (needs IQBIBLE_API_KEY) - Sharing: co-teacher editing via single-use invite links; read-only links can expire and take a passcode Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
34 lines
1.7 KiB
JavaScript
34 lines
1.7 KiB
JavaScript
// Today's verse of the day for the push notification: IQ Bible picks it (the same verse for everyone each UTC day),
|
|
// in the KJV, which is free to quote. Needs IQBIBLE_API_KEY on the server. One lookup a day serves every user.
|
|
import { bookNameFor } from './bibleApi.js';
|
|
|
|
let cached = null; // { date, verse }
|
|
|
|
export const votdAvailable = () => Boolean(process.env.IQBIBLE_API_KEY);
|
|
|
|
// IQ Bible's answer -> { reference, text }, or null when it isn't one we can use
|
|
export function parseVotd(body) {
|
|
const d = body?.data;
|
|
const book = bookNameFor(d?.book_usfm);
|
|
if (!book || !d?.chapter_number || !d?.verse_number || typeof d.text !== 'string' || !d.text.trim()) return null;
|
|
return { reference: `${book} ${d.chapter_number}:${d.verse_number}`, text: d.text.replace(/^[¶§*\s]+/, '').replace(/\s+/g, ' ').trim() };
|
|
}
|
|
|
|
export async function fetchVerseOfDay(now = new Date(), fetcher = fetch) {
|
|
const date = now.toISOString().slice(0, 10);
|
|
if (cached?.date === date) return cached.verse;
|
|
if (!votdAvailable()) return null;
|
|
const base = (process.env.IQBIBLE_API_BASE || 'https://api.iqbible.com/api/v2').replace(/\/+$/, '');
|
|
try {
|
|
const res = await fetcher(`${base}/bibles/eng_kjv/verse-of-the-day`, { headers: { 'X-IQBible-API-Key': process.env.IQBIBLE_API_KEY }, signal: AbortSignal.timeout(10_000) });
|
|
if (!res.ok) return null;
|
|
const verse = parseVotd(await res.json());
|
|
if (verse) cached = { date, verse };
|
|
return verse;
|
|
} catch { return null; }
|
|
}
|
|
|
|
export const clearVotdCache = () => { cached = null; };
|
|
|
|
export const votdMessage = ({ reference, text }) => ({ title: `Verse of the day: ${reference}`, body: `${text}\n\n${reference} (KJV)`, tags: 'sunrise' });
|