288 lines
9.4 KiB
JavaScript
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;
|