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

288 lines
9.4 KiB
JavaScript

const DBName = "EMI_SOCIAL";
const toProfileIds = (DB, profileIds = []) => {
return profileIds
.filter((profileId) => DB.ObjectID.isValid(profileId))
.map((profileId) => DB.ObjectID(profileId));
};
const publicProfile = (profile) => {
if (!profile) return null;
return {
_id: profile._id,
profile: profile.profile,
username: profile.username,
isGroup: profile.isGroup,
isCourse: profile.isCourse,
};
};
const bibleDB = (DB) => {
DB.bibleVerseCols = DB.db.db(DBName).collection("bible_verses");
DB.bibleVerseCols.createIndex({ highlightedBy: 1 }).catch(console.error);
DB.bibleVerseCols.createIndex({ notedBy: 1 }).catch(console.error);
const getVerseDoc = async (verseKey) => {
return DB.bibleVerseCols.findOne({ _id: verseKey }).catch((err) => {
console.log(err);
return false;
});
};
DB.getBibleProfileData = async (profileid) => {
if (!DB.ObjectID.isValid(profileid)) return false;
const profile = await DB.profileCols.findOne(
{ _id: DB.ObjectID(profileid) },
{ projection: { bibleHighlights: 1, bibleNotes: 1 } }
).catch((err) => {
console.log(err);
return false;
});
return {
highlights: profile?.bibleHighlights || [],
notes: profile?.bibleNotes || [],
};
};
DB.getBibleVerseCounters = async (verseKey) => {
const verse = await getVerseDoc(verseKey);
const highlightedBy = Array.isArray(verse?.highlightedBy) ? verse.highlightedBy : [];
const notedBy = Array.isArray(verse?.notedBy) ? verse.notedBy : [];
return {
verseKey,
highlightCount: highlightedBy.length,
noteProfileCount: notedBy.length,
notesCount: verse?.notesCount || 0,
};
};
DB.getBibleVerseActivity = async (verseKey, limit = 10) => {
const verse = await getVerseDoc(verseKey);
const highlightedBy = Array.isArray(verse?.highlightedBy) ? verse.highlightedBy : [];
const notedBy = Array.isArray(verse?.notedBy) ? verse.notedBy : [];
const highlightProfiles = toProfileIds(DB, highlightedBy);
const noteProfiles = toProfileIds(DB, notedBy);
const [highlights, noteUsers, notes] = await Promise.all([
highlightProfiles.length
? DB.profileCols.find({ _id: { $in: highlightProfiles } }).project({
profile: 1,
username: 1,
isGroup: 1,
isCourse: 1,
}).toArray()
: [],
noteProfiles.length
? DB.profileCols.find({ _id: { $in: noteProfiles } }).project({
profile: 1,
username: 1,
isGroup: 1,
isCourse: 1,
}).toArray()
: [],
DB.profileCols.aggregate([
{ $match: { "bibleNotes.verseKey": verseKey } },
{ $unwind: "$bibleNotes" },
{ $match: { "bibleNotes.verseKey": verseKey } },
{ $sort: { "bibleNotes.updatedAt": -1, "bibleNotes.createdAt": -1 } },
{ $limit: limit },
{
$project: {
_id: 0,
note: "$bibleNotes",
profile: {
_id: "$_id",
profile: "$profile",
username: "$username",
isGroup: "$isGroup",
isCourse: "$isCourse",
}
}
}
]).toArray(),
]);
return {
counters: await DB.getBibleVerseCounters(verseKey),
highlightedBy: highlights.map(publicProfile),
notedBy: noteUsers.map(publicProfile),
notes,
};
};
DB.addBibleHighlight = async (profileid, verseKey) => {
if (!DB.ObjectID.isValid(profileid)) return false;
const now = new Date();
const _id = DB.ObjectID(profileid);
const profileUpdate = await DB.profileCols.updateOne(
{ _id, "bibleHighlights.verseKey": { $ne: verseKey } },
{
$push: {
bibleHighlights: {
verseKey,
createdAt: now,
}
},
$set: { lastUpdate: now }
}
).catch((err) => {
console.log(err);
return false;
});
await DB.bibleVerseCols.updateOne(
{ _id: verseKey },
{
$setOnInsert: { createdAt: now },
$set: { updatedAt: now },
$addToSet: { highlightedBy: profileid + "" }
},
{ upsert: true }
).catch((err) => {
console.log(err);
return false;
});
if (DB.clearProfileCache) DB.clearProfileCache(profileid);
return profileUpdate;
};
DB.removeBibleHighlight = async (profileid, verseKey) => {
if (!DB.ObjectID.isValid(profileid)) return false;
const now = new Date();
const _id = DB.ObjectID(profileid);
const profileUpdate = await DB.profileCols.updateOne(
{ _id },
{
$pull: { bibleHighlights: { verseKey } },
$set: { lastUpdate: now }
}
).catch((err) => {
console.log(err);
return false;
});
await DB.bibleVerseCols.updateOne(
{ _id: verseKey },
{
$pull: { highlightedBy: profileid + "" },
$set: { updatedAt: now }
}
).catch((err) => {
console.log(err);
return false;
});
if (DB.clearProfileCache) DB.clearProfileCache(profileid);
return profileUpdate;
};
DB.addBibleNote = async (profileid, verseKey, text) => {
if (!DB.ObjectID.isValid(profileid)) return false;
const now = new Date();
const note = {
_id: DB.ObjectID().toString(),
verseKey,
text,
createdAt: now,
updatedAt: now,
};
const _id = DB.ObjectID(profileid);
const profileUpdate = await DB.profileCols.updateOne(
{ _id },
{
$push: { bibleNotes: note },
$set: { lastUpdate: now }
}
).catch((err) => {
console.log(err);
return false;
});
await DB.bibleVerseCols.updateOne(
{ _id: verseKey },
{
$setOnInsert: { createdAt: now },
$set: { updatedAt: now },
$addToSet: { notedBy: profileid + "" },
$inc: { notesCount: 1 }
},
{ upsert: true }
).catch((err) => {
console.log(err);
return false;
});
if (DB.clearProfileCache) DB.clearProfileCache(profileid);
return profileUpdate ? note : false;
};
DB.updateBibleNote = async (profileid, verseKey, noteId, text) => {
if (!DB.ObjectID.isValid(profileid)) return false;
const now = new Date();
const _id = DB.ObjectID(profileid);
const result = await DB.profileCols.findOneAndUpdate(
{ _id, bibleNotes: { $elemMatch: { _id: noteId, verseKey } } },
{
$set: {
"bibleNotes.$.text": text,
"bibleNotes.$.updatedAt": now,
lastUpdate: now,
}
},
{
returnOriginal: false,
projection: { bibleNotes: 1 }
}
).catch((err) => {
console.log(err);
return false;
});
if (DB.clearProfileCache) DB.clearProfileCache(profileid);
return result?.value?.bibleNotes?.find((note) => note._id === noteId) || null;
};
DB.removeBibleNote = async (profileid, verseKey, noteId) => {
if (!DB.ObjectID.isValid(profileid)) return false;
const now = new Date();
const _id = DB.ObjectID(profileid);
const result = await DB.profileCols.updateOne(
{ _id, bibleNotes: { $elemMatch: { _id: noteId, verseKey } } },
{
$pull: { bibleNotes: { _id: noteId, verseKey } },
$set: { lastUpdate: now }
}
).catch((err) => {
console.log(err);
return false;
});
if (result?.modifiedCount) {
const stillHasNotes = await DB.profileCols.findOne(
{ _id, "bibleNotes.verseKey": verseKey },
{ projection: { _id: 1 } }
);
const verseUpdate = {
$inc: { notesCount: -1 },
$set: { updatedAt: now }
};
if (!stillHasNotes) {
verseUpdate.$pull = { notedBy: profileid + "" };
}
await DB.bibleVerseCols.updateOne({ _id: verseKey }, verseUpdate).catch((err) => {
console.log(err);
return false;
});
}
if (DB.clearProfileCache) DB.clearProfileCache(profileid);
return result;
};
}
module.exports = bibleDB;