diff --git a/package-lock.json b/package-lock.json index e217a963..77df7125 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "i18next": "^22.4.10", "is-online": "^10.0.0", "jsdom": "^21.1.0", - "jw-epub-parser": "^1.33.0", + "jw-epub-parser": "^1.34.0", "node-2fa": "^2.0.3", "node-fetch": "^3.3.0", "nodemailer": "^6.9.1", @@ -8520,9 +8520,9 @@ } }, "node_modules/jw-epub-parser": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/jw-epub-parser/-/jw-epub-parser-1.33.0.tgz", - "integrity": "sha512-jKl4GEurpocCRI+h/VKQbpSYvbTpth5Hn1I3/JVTQsvZ430XCFAt5C72pABxe49ajhh/ZLrr18B2+fnvTH+uYQ==", + "version": "1.34.0", + "resolved": "https://registry.npmjs.org/jw-epub-parser/-/jw-epub-parser-1.34.0.tgz", + "integrity": "sha512-uxMFWefl7s1iJAaCGk8E8ajY4H2SulzjOaVlgYFcpRGkW1zHmbOrZOB0tR5INBHRfFepnmGnvHq3haLT5GZ95Q==", "dependencies": { "dateformat": "^5.0.3", "global-jsdom": "^8.7.0", @@ -21914,9 +21914,9 @@ } }, "jw-epub-parser": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/jw-epub-parser/-/jw-epub-parser-1.33.0.tgz", - "integrity": "sha512-jKl4GEurpocCRI+h/VKQbpSYvbTpth5Hn1I3/JVTQsvZ430XCFAt5C72pABxe49ajhh/ZLrr18B2+fnvTH+uYQ==", + "version": "1.34.0", + "resolved": "https://registry.npmjs.org/jw-epub-parser/-/jw-epub-parser-1.34.0.tgz", + "integrity": "sha512-uxMFWefl7s1iJAaCGk8E8ajY4H2SulzjOaVlgYFcpRGkW1zHmbOrZOB0tR5INBHRfFepnmGnvHq3haLT5GZ95Q==", "requires": { "dateformat": "^5.0.3", "global-jsdom": "^8.7.0", diff --git a/package.json b/package.json index c0036afe..d5caa6e3 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "i18next": "^22.4.10", "is-online": "^10.0.0", "jsdom": "^21.1.0", - "jw-epub-parser": "^1.33.0", + "jw-epub-parser": "^1.34.0", "node-2fa": "^2.0.3", "node-fetch": "^3.3.0", "nodemailer": "^6.9.1", diff --git a/src/classes/Congregation.js b/src/classes/Congregation.js index 5ae61104..0916952e 100644 --- a/src/classes/Congregation.js +++ b/src/classes/Congregation.js @@ -3,6 +3,7 @@ import randomstring from 'randomstring'; import { FieldValue, getFirestore } from 'firebase-admin/firestore'; import { decryptData, encryptData } from '../utils/encryption-utils.js'; import { users } from './Users.js'; +import { getOldestWeekDate, getWeekDate } from '../utils/date.js'; const db = getFirestore(); //get default database @@ -105,6 +106,8 @@ Congregation.prototype.saveBackup = async function ( cong_settings, uid ) { + const oldestWeekDate = getOldestWeekDate(); + let finalPersons = []; // new backup persons @@ -248,107 +251,130 @@ Congregation.prototype.saveBackup = async function ( // new backup schedule if (this.cong_schedule_draft.length === 0) { - finalSchedule = cong_schedule; + cong_schedule.forEach((schedule) => { + const weekOfDate = getWeekDate(schedule.weekOf); + + if (weekOfDate >= oldestWeekDate) { + finalSchedule.push(schedule); + } + }); } // updated schedule if (this.cong_schedule_draft.length > 0) { // handle modified schedule this.cong_schedule_draft.forEach((oldSchedule) => { - const newSchedule = cong_schedule.find((schedule) => schedule.weekOf === oldSchedule.weekOf); - if (newSchedule) { - const oldChanges = oldSchedule.changes; - const newChanges = newSchedule.changes; + const weekOfDate = getWeekDate(oldSchedule.weekOf); - if (newChanges) { - newChanges.forEach((change) => { - let isChanged = false; + if (weekOfDate >= oldestWeekDate) { + const newSchedule = cong_schedule.find((schedule) => schedule.weekOf === oldSchedule.weekOf); + if (newSchedule) { + const oldChanges = oldSchedule.changes; + const newChanges = newSchedule.changes; - const oldChange = oldChanges?.find((old) => old.field === change.field); - const originalDate = oldChange?.date || undefined; - - if (!oldChange) { - isChanged = true; - } + if (newChanges) { + newChanges.forEach((change) => { + let isChanged = false; - if (originalDate) { - const dateA = new Date(originalDate); - const dateB = new Date(change.date); + const oldChange = oldChanges?.find((old) => old.field === change.field); + const originalDate = oldChange?.date || undefined; - if (dateB > dateA) { + if (!oldChange) { isChanged = true; } - } - if (isChanged) { - oldSchedule[change.field] = change.value || null; + if (originalDate) { + const dateA = new Date(originalDate); + const dateB = new Date(change.date); - if (oldSchedule.changes) { - const findIndex = oldSchedule.changes.findIndex((item) => item.field === change.field) || -1; - if (findIndex !== -1) oldSchedule.changes.splice(findIndex, 1); + if (dateB > dateA) { + isChanged = true; + } } - if (!oldSchedule.changes) { - oldSchedule.changes = []; - } + if (isChanged) { + oldSchedule[change.field] = change.value || null; - oldSchedule.changes.push(change); - } - }); + if (oldSchedule.changes) { + const findIndex = oldSchedule.changes.findIndex((item) => item.field === change.field) || -1; + if (findIndex !== -1) oldSchedule.changes.splice(findIndex, 1); + } + + if (!oldSchedule.changes) { + oldSchedule.changes = []; + } + + oldSchedule.changes.push(change); + } + }); + } } - } - finalSchedule.push(oldSchedule); + finalSchedule.push(oldSchedule); + } }); // handle new schedule record cong_schedule.forEach((newSchedule) => { - const oldSchedule = this.cong_schedule_draft.find((schedule) => schedule.weekOf === newSchedule.weekOf); - if (!oldSchedule) { - finalSchedule.push(newSchedule); + const weekOfDate = getWeekDate(newSchedule.weekOf); + const oldestWeekDate = getOldestWeekDate(); + + if (weekOfDate >= oldestWeekDate) { + const oldSchedule = this.cong_schedule_draft.find((schedule) => schedule.weekOf === newSchedule.weekOf); + if (!oldSchedule) { + finalSchedule.push(newSchedule); + } } }); } cong_sourceMaterial.forEach((newSource) => { - const oldSource = this.cong_sourceMaterial_draft.find((source) => source.weekOf === newSource.weekOf); - const oldSourceIndex = this.cong_sourceMaterial_draft.findIndex((source) => source.weekOf === newSource.weekOf); - - if (!oldSource) { - this.cong_sourceMaterial_draft.push(newSource); - } + const weekOfDate = getWeekDate(newSource.weekOf); - if (oldSource) { - // restore keepOverride if qualified - const newKeepOverride = newSource.keepOverride || undefined; - const oldKeepOverride = oldSource ? oldSource.keepOverride : undefined; - let isRestore = false; + if (weekOfDate >= oldestWeekDate) { + const oldSource = this.cong_sourceMaterial_draft.find((source) => source.weekOf === newSource.weekOf); + const oldSourceIndex = this.cong_sourceMaterial_draft.findIndex((source) => source.weekOf === newSource.weekOf); - if (!newKeepOverride) { - isRestore = true; + if (!oldSource) { + this.cong_sourceMaterial_draft.push(newSource); } - if (newKeepOverride && oldKeepOverride) { - const oldDate = new Date(oldKeepOverride); - const newDate = new Date(newKeepOverride); + if (oldSource) { + // restore keepOverride if qualified + const newKeepOverride = newSource.keepOverride || undefined; + const oldKeepOverride = oldSource ? oldSource.keepOverride : undefined; + let isRestore = false; - if (oldDate > newDate) { + if (!newKeepOverride) { isRestore = true; } - } - if (isRestore) { - for (const [key, value] of Object.entries(oldSource)) { - if (key.indexOf('_override') !== -1) { - if (value) newSource[key] = value; + if (newKeepOverride && oldKeepOverride) { + const oldDate = new Date(oldKeepOverride); + const newDate = new Date(newKeepOverride); + + if (oldDate > newDate) { + isRestore = true; } } - this.cong_sourceMaterial_draft.splice(oldSourceIndex, 1, newSource); + if (isRestore) { + for (const [key, value] of Object.entries(oldSource)) { + if (key.indexOf('_override') !== -1) { + if (value) newSource[key] = value; + } + } + + this.cong_sourceMaterial_draft.splice(oldSourceIndex, 1, newSource); + } } } }); + this.cong_sourceMaterial_draft = this.cong_sourceMaterial_draft.filter( + (source) => getWeekDate(source.weekOf) >= oldestWeekDate + ); + const userInfo = users.findUserByAuthUid(uid); const buffer = Buffer.from(encryptedPersons, 'utf-8'); diff --git a/src/controllers/public-controller.js b/src/controllers/public-controller.js index 6dc417c0..87459255 100644 --- a/src/controllers/public-controller.js +++ b/src/controllers/public-controller.js @@ -4,10 +4,11 @@ import { extractScheduleDocsId, fetchData } from '../utils/public-utils.js'; export const getSchedules = async (req, res, next) => { try { let { language } = req.params; + const issue = req.headers.issuedate || ''; language = language.toUpperCase(); - const mergedSources = await fetchData(language); + const mergedSources = await fetchData(language, issue); if (mergedSources.length > 0) { res.locals.type = 'info'; diff --git a/src/utils/date.js b/src/utils/date.js new file mode 100644 index 00000000..1b158e78 --- /dev/null +++ b/src/utils/date.js @@ -0,0 +1,16 @@ +export const getWeekDate = (weekOf) => { + const month = +weekOf.split('/')[0] - 1; + const day = +weekOf.split('/')[1]; + const year = +weekOf.split('/')[2]; + + return new Date(year, month, day); +}; + +export const getOldestWeekDate = () => { + const today = new Date(); + const day = today.getDay(); + const diff = today.getDate() - day + (day === 0 ? -6 : 1); + const weekDate = new Date(today.setDate(diff)); + const validDate = weekDate.setMonth(weekDate.getMonth() - 12); + return new Date(validDate); +}; diff --git a/src/utils/public-utils.js b/src/utils/public-utils.js index d73ce34b..14d8c753 100644 --- a/src/utils/public-utils.js +++ b/src/utils/public-utils.js @@ -18,33 +18,70 @@ export const fetchIssueData = (issue) => { resolve(obj); }); } + + if (!issue.hasEPUB) { + resolve({}); + } }); }; -export const fetchData = async (language) => { +export const fetchData = async (language, issue) => { const mergedSources = []; let notFound = false; - // get current issue - const today = new Date(); - const day = today.getDay(); - const diff = today.getDate() - day + (day === 0 ? -6 : 1); - const weekDate = new Date(today.setDate(diff)); - const currentMonth = weekDate.getMonth() + 1; - const monthOdd = currentMonth % 2 === 0 ? false : true; - let monthMwb = monthOdd ? currentMonth : currentMonth - 1; - let currentYear = weekDate.getFullYear(); - - monthMwb = monthMwb - 2; - if (monthMwb === -1) { - monthMwb = 11; - currentYear--; - } - const issues = []; - do { - const issueDate = currentYear + String(monthMwb).padStart(2, '0'); + if (issue === '') { + // get current issue + const today = new Date(); + const day = today.getDay(); + const diff = today.getDate() - day + (day === 0 ? -6 : 1); + const weekDate = new Date(today.setDate(diff)); + const validDate = weekDate.setMonth(weekDate.getMonth()); + + const startDate = new Date(validDate); + const currentMonth = startDate.getMonth() + 1; + const monthOdd = currentMonth % 2 === 0 ? false : true; + let monthMwb = monthOdd ? currentMonth : currentMonth - 1; + let currentYear = startDate.getFullYear(); + + do { + if ((currentYear === 2022 && monthMwb > 5) || currentYear > 2022) { + const issueDate = currentYear + String(monthMwb).padStart(2, '0'); + const url = + process.env.JW_CDN + + new URLSearchParams({ + langwritten: language, + pub: 'mwb', + fileformat: 'epub', + output: 'json', + issue: issueDate, + }); + + const res = await fetch(url); + + if (res.status === 200) { + const result = await res.json(); + const hasEPUB = result.files[language].EPUB; + + issues.push({ issueDate, currentYear, language, hasEPUB: hasEPUB }); + } + + if (res.status === 404) { + notFound = true; + } + } + + // assigning next issue + monthMwb = monthMwb + 2; + if (monthMwb === 13) { + monthMwb = 1; + currentYear++; + } + } while (notFound === false); + } + + if (issue !== '') { const url = process.env.JW_CDN + new URLSearchParams({ @@ -52,7 +89,7 @@ export const fetchData = async (language) => { pub: 'mwb', fileformat: 'epub', output: 'json', - issue: issueDate, + issue, }); const res = await fetch(url); @@ -60,29 +97,20 @@ export const fetchData = async (language) => { if (res.status === 200) { const result = await res.json(); const hasEPUB = result.files[language].EPUB; - - issues.push({ issueDate, currentYear, language, hasEPUB: hasEPUB }); - } - - if (res.status === 404) { - notFound = true; + const currentYear = issue.substring(0, 4); + issues.push({ issueDate: issue, currentYear, language, hasEPUB: hasEPUB }); } - - // assigning next issue - monthMwb = monthMwb + 2; - if (monthMwb === 13) { - monthMwb = 1; - currentYear++; - } - } while (notFound === false); + } if (issues.length > 0) { const fetchSource1 = fetchIssueData(issues[0]); const fetchSource2 = issues.length > 1 ? fetchIssueData(issues[1]) : Promise.resolve({}); const fetchSource3 = issues.length > 2 ? fetchIssueData(issues[2]) : Promise.resolve({}); const fetchSource4 = issues.length > 3 ? fetchIssueData(issues[3]) : Promise.resolve({}); + const fetchSource5 = issues.length > 4 ? fetchIssueData(issues[4]) : Promise.resolve({}); + const fetchSource6 = issues.length > 5 ? fetchIssueData(issues[5]) : Promise.resolve({}); - const allData = await Promise.all([fetchSource1, fetchSource2, fetchSource3, fetchSource4]); + const allData = await Promise.all([fetchSource1, fetchSource2, fetchSource3, fetchSource4, fetchSource5, fetchSource6]); for (let z = 0; z < allData.length; z++) { const tempObj = allData[z];