Files
EMI-Backend/routes/bible.js
T
2026-05-28 20:45:41 -04:00

534 lines
14 KiB
JavaScript

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