Add Bible verse highlights and notes API

This commit is contained in:
Adolfo Reyna
2026-05-28 20:45:41 -04:00
parent ef7c24c884
commit 65a4178e2b
6 changed files with 617 additions and 3 deletions
+312 -1
View File
@@ -2,6 +2,7 @@ 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/"
@@ -11,6 +12,20 @@ const fetchAPI = async (path) => {
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) => {
/**
@@ -37,6 +52,302 @@ DB.getDB.then((DB) => {
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:
@@ -219,4 +530,4 @@ DB.getDB.then((DB) => {
});
module.exports = router
module.exports = router