diff --git a/src/commands/owner/updateDB.ts b/src/commands/owner/updateDB.ts index 929815a..47f7823 100644 --- a/src/commands/owner/updateDB.ts +++ b/src/commands/owner/updateDB.ts @@ -2,7 +2,9 @@ import { ICommand } from "wokcommands"; import DiscordJS from "discord.js"; import chalk from "chalk"; import axios from "axios"; -import { classModel } from "../../models/classModel"; +import { classModel, IClass } from "../../models/classModel"; +import { Types, Document } from "mongoose"; +import { cleanCourseCode, removeHTML } from "../../utils/course_cleaning"; /** * @description @@ -68,21 +70,19 @@ async function getDescription(course: any, srcdb: string) { * @param srcdb - the semester id to get the courses for * @return - Array of course objects */ -async function getCourseInfo(srcdb: string) { +async function getCoursesWithDescription(srcdb: string) { const courses = await getCourses(srcdb); let info: course[] = []; for (const course of courses) { const description = await getDescription(course, srcdb); let entry: course = { - code: course.code, + code: cleanCourseCode(course.code), title: course.title, - description: description - .replace(/<\/?[^>]+(>|$)/g, "") - .replace(".", ". "), // cleans all html tags and adds spaces after periods + description: removeHTML(description), }; info.push(entry); } - return await info; + return info; } export default { name: "updatedb", @@ -117,40 +117,56 @@ export default { callback: async ({ interaction }) => { interaction.deferReply(); // Defer the reply until all entries have been created or updated const srcdb = interaction.options.getString("semester"); - let currentCourses = await classModel.find({}); - let info = await getCourseInfo(srcdb!); + let current_courses = await classModel.find({}); + let new_courses = await getCoursesWithDescription(srcdb!); // Set all current entries to inactive so when we update the db we can know the ones that are no longer active. they will get moved to the PAST CLASSES category - for (const course of currentCourses) { + current_courses.forEach((course) => { course.ACTIVE = false; - await course.save(); - } + }); + + let courses_to_save: (Document & + IClass & { _id: Types.ObjectId })[] = []; // Loop through all the new classes info and update current entries or create new ones - for (const entry of info) { - const name = entry.code.toLowerCase().replace("compsci ", "cs").trim(); - let currentCourse = await classModel.findOne({ NAME: name }); - if (currentCourse) { - currentCourse.ACTIVE = true; - currentCourse.NAME = name; - currentCourse.TITLE = entry.title; - currentCourse.INFO = entry.description - .replace(/<\/?[^>]+(>|$)/g, "") - .replace(".", ". "); // cleans all html tags and adds spaces after periods - await currentCourse.save(); - } else { + for (const new_course of new_courses) { + let found_courses = await classModel.find({ NAME: new_course.code }); + if (found_courses === undefined || found_courses.length === 0) { const newClass = new classModel({ - NAME: name, - TITLE: entry.title, - INFO: entry.description - .replace(/<\/?[^>]+(>|$)/g, "") - .replace(".", ". "), // cleans all html tags and adds spaces after periods + NAME: new_course.code, + TITLE: new_course.title, + INFO: new_course.description, ACTIVE: true, + DUPE: false, }); - await newClass.save(); // ROLE_NAME, ROLE_ID, CHANNEL_ID, DUPE will be added later by using createRoles, csCreateChannels, and migrateDB + courses_to_save.push(newClass); + } else { + let found_dupe = false; + const multiple_results = found_courses.length > 1 ? true : false; // If there are multiple results for a class then it is a duplicate + for (const found_course of found_courses) { + found_course.DUPE = multiple_results; + if (found_course.TITLE === new_course.title) { + found_course.ACTIVE = true; + found_course.NAME = new_course.code; + found_course.INFO = new_course.description; + found_dupe = true; + } + } + if (found_dupe === false) { + const newClass = new classModel({ + NAME: new_course.code, + TITLE: new_course.title, + INFO: new_course.description, + ACTIVE: true, + DUPE: multiple_results, + }); + courses_to_save.push(newClass); + } } } + await classModel.bulkSave(courses_to_save); + await classModel.bulkSave(current_courses); //TODO: Reply to interaction when all classes are updated // Log the command usage diff --git a/src/utils/course_cleaning.ts b/src/utils/course_cleaning.ts new file mode 100644 index 0000000..4870546 --- /dev/null +++ b/src/utils/course_cleaning.ts @@ -0,0 +1,27 @@ +const shorteningMap = new Map([["compsci", "cs"]]); + +/** + * @description - Cleans a course code by removing spaces and replacing matches in the shorteningMap + * @author John Schiltz + * @export + * @param course_code - the course code to clean + * @return {*} - the cleaned course code + */ +export function cleanCourseCode(course_code: string): string { + let clean_course_code = course_code.toLowerCase(); + shorteningMap.forEach((value, key) => { + clean_course_code = clean_course_code.replace(key, value); + }); + return clean_course_code.trim(); +} + +/** + * @description - Removes all html tags from a string and adds spaces after periods + * @author Nathen Goldsborough + * @export + * @param s + * @return {*} + */ +export function removeHTML(s: string): string { + return s.replace(/<\/?[^>]+(>|$)/g, "").replace(".", ". "); +}