534 lines
14 KiB
JavaScript
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
|