Add Bible verse highlights and notes API
This commit is contained in:
+312
-1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user