const axios = require('axios'); var express = require('express') var router = express.Router() const DB = require("./../mongoDB.js"); const { getProfileId } = require("./../utils/sessionUtils.js"); const fetchAPI = async (path) => { baseUrl = "https://api.scripture.api.bible/v1/" let detailHtml = await axios.get(baseUrl + path, {headers:{'api-key':'8b43472a173a39e04cd868fd4848ed75'}}).catch(console.error); return detailHtml?.data; } const defaultBibleId = "592420522e16049f-01"; const normalizeVerseKey = (verseKey) => { if (!verseKey || typeof verseKey !== "string") return ""; return verseKey.trim().toUpperCase(); }; const isValidVerseKey = (verseKey) => { return /^[A-Z0-9]+(\.[A-Z0-9]+)+$/.test(verseKey); }; const getNoteText = (req) => { const text = req.body?.text || req.body?.note || ""; return typeof text === "string" ? text.trim() : ""; }; //getMedia('y42zyf3').then(console.log) DB.getDB.then((DB) => { /** * @swagger * tags: * name: Bible * description: Bible API */ /** * @swagger * /bible: * get: * summary: Get a list of available Bibles * tags: [Bible] * security: * - cookieAuth: [] * responses: * 200: * description: OK */ router.get("", async (req, res) => { const bibles = await fetchAPI('bibles'); return res.json(bibles); }); /** * @swagger * /bible/mine: * get: * summary: Get Bible highlights and notes for the active profile * tags: [Bible] * security: * - cookieAuth: [] * responses: * 200: * description: OK */ router.get("/mine", async (req, res) => { const profileid = getProfileId(req); const bibleData = await DB.getBibleProfileData(profileid); if (!bibleData) return res.status(400).json({ status: "Invalid profile" }); return res.json({ status: "ok", ...bibleData }); }); /** * @swagger * /bible/verses/{verseKey}/counters: * get: * summary: Get highlight and note counters for a Bible verse * tags: [Bible] * security: * - cookieAuth: [] * parameters: * - in: path * name: verseKey * required: true * schema: * type: string * example: GEN.1.1 * responses: * 200: * description: OK */ router.get("/verses/:verseKey/counters", async (req, res) => { const verseKey = normalizeVerseKey(req.params.verseKey); if (!isValidVerseKey(verseKey)) { return res.status(400).json({ status: "Invalid verse key" }); } const counters = await DB.getBibleVerseCounters(verseKey); return res.json({ status: "ok", ...counters }); }); /** * @swagger * /bible/verses/{verseKey}/activity: * get: * summary: Get profiles and recent notes for a Bible verse * tags: [Bible] * security: * - cookieAuth: [] * parameters: * - in: path * name: verseKey * required: true * schema: * type: string * example: GEN.1.1 * - in: query * name: limit * schema: * type: integer * default: 10 * responses: * 200: * description: OK */ router.get("/verses/:verseKey/activity", async (req, res) => { const verseKey = normalizeVerseKey(req.params.verseKey); if (!isValidVerseKey(verseKey)) { return res.status(400).json({ status: "Invalid verse key" }); } const limit = Math.min(Math.max(parseInt(req.query.limit, 10) || 10, 1), 10); const activity = await DB.getBibleVerseActivity(verseKey, limit); return res.json({ status: "ok", verseKey, ...activity }); }); /** * @swagger * /bible/verses/{verseKey}/highlight: * post: * summary: Highlight a Bible verse for the active profile * tags: [Bible] * security: * - cookieAuth: [] * parameters: * - in: path * name: verseKey * required: true * schema: * type: string * example: GEN.1.1 * responses: * 200: * description: OK */ router.post("/verses/:verseKey/highlight", async (req, res) => { const profileid = getProfileId(req); const verseKey = normalizeVerseKey(req.params.verseKey); if (!isValidVerseKey(verseKey)) { return res.status(400).json({ status: "Invalid verse key" }); } const result = await DB.addBibleHighlight(profileid, verseKey); if (!result) return res.status(400).json({ status: "Could not add highlight" }); const counters = await DB.getBibleVerseCounters(verseKey); return res.json({ status: "ok", highlighted: true, ...counters }); }); /** * @swagger * /bible/verses/{verseKey}/highlight: * delete: * summary: Remove a Bible verse highlight for the active profile * tags: [Bible] * security: * - cookieAuth: [] * parameters: * - in: path * name: verseKey * required: true * schema: * type: string * example: GEN.1.1 * responses: * 200: * description: OK */ router.delete("/verses/:verseKey/highlight", async (req, res) => { const profileid = getProfileId(req); const verseKey = normalizeVerseKey(req.params.verseKey); if (!isValidVerseKey(verseKey)) { return res.status(400).json({ status: "Invalid verse key" }); } const result = await DB.removeBibleHighlight(profileid, verseKey); if (!result) return res.status(400).json({ status: "Could not remove highlight" }); const counters = await DB.getBibleVerseCounters(verseKey); return res.json({ status: "ok", highlighted: false, ...counters }); }); /** * @swagger * /bible/verses/{verseKey}/notes: * post: * summary: Add a Bible verse note for the active profile * tags: [Bible] * security: * - cookieAuth: [] * parameters: * - in: path * name: verseKey * required: true * schema: * type: string * example: GEN.1.1 * responses: * 200: * description: OK */ router.post("/verses/:verseKey/notes", async (req, res) => { const profileid = getProfileId(req); const verseKey = normalizeVerseKey(req.params.verseKey); const text = getNoteText(req); if (!isValidVerseKey(verseKey)) { return res.status(400).json({ status: "Invalid verse key" }); } if (!text) return res.status(400).json({ status: "Note text is required" }); const note = await DB.addBibleNote(profileid, verseKey, text); if (!note) return res.status(400).json({ status: "Could not add note" }); const counters = await DB.getBibleVerseCounters(verseKey); return res.json({ status: "ok", verseKey, note, counters }); }); /** * @swagger * /bible/verses/{verseKey}/notes/{noteId}: * put: * summary: Update a Bible verse note for the active profile * tags: [Bible] * security: * - cookieAuth: [] * parameters: * - in: path * name: verseKey * required: true * schema: * type: string * example: GEN.1.1 * - in: path * name: noteId * required: true * schema: * type: string * responses: * 200: * description: OK */ router.put("/verses/:verseKey/notes/:noteId", async (req, res) => { const profileid = getProfileId(req); const verseKey = normalizeVerseKey(req.params.verseKey); const noteId = req.params.noteId; const text = getNoteText(req); if (!isValidVerseKey(verseKey)) { return res.status(400).json({ status: "Invalid verse key" }); } if (!text) return res.status(400).json({ status: "Note text is required" }); const note = await DB.updateBibleNote(profileid, verseKey, noteId, text); if (!note) return res.status(404).json({ status: "Note not found" }); return res.json({ status: "ok", verseKey, note }); }); /** * @swagger * /bible/verses/{verseKey}/notes/{noteId}: * delete: * summary: Delete a Bible verse note for the active profile * tags: [Bible] * security: * - cookieAuth: [] * parameters: * - in: path * name: verseKey * required: true * schema: * type: string * example: GEN.1.1 * - in: path * name: noteId * required: true * schema: * type: string * responses: * 200: * description: OK */ router.delete("/verses/:verseKey/notes/:noteId", async (req, res) => { const profileid = getProfileId(req); const verseKey = normalizeVerseKey(req.params.verseKey); const noteId = req.params.noteId; if (!isValidVerseKey(verseKey)) { return res.status(400).json({ status: "Invalid verse key" }); } const result = await DB.removeBibleNote(profileid, verseKey, noteId); if (!result) return res.status(400).json({ status: "Could not delete note" }); if (!result.modifiedCount) return res.status(404).json({ status: "Note not found" }); const counters = await DB.getBibleVerseCounters(verseKey); return res.json({ status: "ok", verseKey, deleted: true, counters }); }); /** * @swagger * /bible/books: * get: * summary: Get the books of a Bible * tags: [Bible] * security: * - cookieAuth: [] * parameters: * - in: query * name: bibleId * schema: * type: string * responses: * 200: * description: OK */ router.get("/books", async (req, res) => { const bibleId = req.query.bibleId || defaultBibleId; const bibles = await fetchAPI('bibles/' + bibleId +"/books"); return res.json(bibles); }); router.get("/books", async (req, res) => { const bibleId = req.query.bibleId || defaultBibleId; const bibles = await fetchAPI('bibles/' + bibleId +"/books"); return res.json(bibles); }); /** * @swagger * /bible/books/{bookId}: * get: * summary: Get details for a specific book * tags: [Bible] * security: * - cookieAuth: [] * parameters: * - in: path * name: bookId * required: true * schema: * type: string * - in: query * name: bibleId * schema: * type: string * responses: * 200: * description: OK */ router.get("/books/:bookId", async (req, res) => { const bookId = req.params.bookId; const bibles = await fetchAPI('bibles/' + bibleId +"/books/" + bookId); return res.json(bibles); }); /** * @swagger * /bible/books/{bookId}/chapters: * get: * summary: Get the chapters of a book * tags: [Bible] * security: * - cookieAuth: [] * parameters: * - in: path * name: bookId * required: true * schema: * type: string * - in: query * name: bibleId * schema: * type: string * responses: * 200: * description: OK */ router.get("/books/:bookId/chapters", async (req, res) => { const bookId = req.params.bookId; const bibleId = req.query.bibleId || defaultBibleId; const bibles = await fetchAPI('bibles/' + bibleId +"/books/" + bookId + "/chapters"); return res.json(bibles); }); /** * @swagger * /bible/chapters/{chapterId}: * get: * summary: Get the content of a chapter * tags: [Bible] * security: * - cookieAuth: [] * parameters: * - in: path * name: chapterId * required: true * schema: * type: string * - in: query * name: bibleId * schema: * type: string * responses: * 200: * description: OK */ router.get("/chapters/:chapterId", async (req, res) => { const chapterId = req.params.chapterId; const bibleId = req.query.bibleId || defaultBibleId; const contentType = req.query['content-type'] ? `?content-type=${req.query['content-type']}` : ''; const bibles = await fetchAPI('bibles/' + bibleId + "/chapters/" + chapterId + contentType); return res.json(bibles); }); /** * @swagger * /bible/chapters/{chapterId}/verses: * get: * summary: Get the verses of a chapter * tags: [Bible] * security: * - cookieAuth: [] * parameters: * - in: path * name: chapterId * required: true * schema: * type: string * - in: query * name: bibleId * schema: * type: string * responses: * 200: * description: OK */ router.get("/chapters/:chapterId/verses", async (req, res) => { const chapterId = req.params.chapterId; const bibleId = req.query.bibleId || defaultBibleId; const bibles = await fetchAPI('bibles/' + bibleId + "/chapters/" + chapterId + "/verses"); return res.json(bibles); }); /** * @swagger * /bible/search: * get: * summary: Search the Bible * tags: [Bible] * security: * - cookieAuth: [] * parameters: * - in: query * name: query * required: true * schema: * type: string * - in: query * name: limit * schema: * type: integer * default: 10 * - in: query * name: bibleId * schema: * type: string * responses: * 200: * description: OK */ router.get("/search", async (req, res) => { const query = req.query.query; const limit = req.query.limit || 10; const bibleId = req.query.bibleId || defaultBibleId; const bibles = await fetchAPI('bibles/' + bibleId + "/search?query=" + query + "&limit=" + limit); return res.json(bibles); }); }); module.exports = router