@wyteco/berkeley-ical
Version:
A command line tool to easily export your classes from the Berkeley Academic Guide to your calendar in iCal (.ics) format. Without having a student account lol!
126 lines • 5.13 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.propertyLookup = void 0;
//
const helpers_1 = require("./helpers");
// ----------------------------------------------------------------------
/**
* This code might need to be updated if the website changes.
* The selectors are used to extract the course data from the HTML content.
* Note that each `transform` function returns the type of the corresponding
* property in the `CourseData` type.
*
* This code expects the data to be from the Berkeley Academic Guide
* course pages like `https://classes.berkeley.edu/content/2025-spring-compsci-c280-001-lec-001`.
*/
exports.propertyLookup = {
title: {
query: 'h2.sf--course-title',
transform: (textValue) => textValue.trim(),
},
description: {
query: 'section#section-course-description div.section-content',
transform: (textValue) => textValue.trim(),
},
instructors: {
query: 'div.sf--details div.sf--instructors p',
transform: (textValue) => {
return textValue.split(',').map((instructor) => instructor.trim());
},
},
startDate: {
query: 'div.sf--details div.sf--meeting-dates',
transform: (textValue) => {
var _a;
const startDateText = (_a = textValue.split('-').at(0)) === null || _a === void 0 ? void 0 : _a.trim();
if (!startDateText) {
console.log('');
console.warn(`Invalid date range string: "${textValue}". No start date found. Trying to parse as a single date.`);
return (0, helpers_1.parseDateString)(textValue);
}
return (0, helpers_1.parseDateString)(startDateText);
},
},
endDate: {
query: 'div.sf--details div.sf--meeting-dates',
transform: (textValue) => {
var _a;
const endDateText = (_a = textValue.split('-').at(1)) === null || _a === void 0 ? void 0 : _a.trim();
if (!endDateText) {
console.log('');
console.warn(`Invalid date range string: "${textValue}". No end date found. Using null as end date.`);
return null;
}
return (0, helpers_1.parseDateString)(endDateText);
},
},
meetingDays: {
query: 'div.sf--details div.sf--meeting-days',
transform: (textValue) => {
return textValue.split(',').map((day) => {
var _a;
const weekday = (_a = Object.entries(helpers_1.weekdayLookup)
.find(([weekday, values]) => values.includes(day.toLowerCase().trim()))) === null || _a === void 0 ? void 0 : _a.at(0);
if (!weekday) {
console.log('');
throw new Error(`Invalid weekday: "${day.trim()}"`);
}
return weekday;
});
},
},
meetingStartTime: {
query: 'div.sf--details div.sf--meeting-time',
transform: (textValue) => {
var _a;
const startTime = (_a = textValue.split('-').at(0)) === null || _a === void 0 ? void 0 : _a.trim();
if (!startTime) {
console.log('');
throw new Error(`Invalid time range string: "${textValue}"`);
}
return (0, helpers_1.parseTimeString)(startTime);
},
},
meetingEndTime: {
query: 'div.sf--details div.sf--meeting-time',
transform: (textValue) => {
var _a;
const endTime = (_a = textValue.split('-').at(1)) === null || _a === void 0 ? void 0 : _a.trim();
if (!endTime) {
console.log('');
console.warn(`Invalid time range string: "${textValue}". No end time found. Using null as end time.`);
return null;
}
return (0, helpers_1.parseTimeString)(endTime);
},
},
location: {
query: 'div.sf--details div.sf--location',
transform: (textValue) => textValue.trim(),
},
numberOfEnrollments: {
query: 'section.current-enrollment .stats div:contains("Enrolled:")',
transform: (textValue) => {
var _a;
const numberOfEnrollments = (_a = textValue.match(/\d+/)) === null || _a === void 0 ? void 0 : _a[0];
if (!numberOfEnrollments) {
console.log('');
throw new Error(`Invalid number of enrollments string: "${textValue}"`);
}
return parseInt(numberOfEnrollments, 10);
},
},
capacity: {
query: 'section.current-enrollment .stats div:contains("Capacity:")',
transform: (textValue) => {
var _a;
const capacity = (_a = textValue.match(/\d+/)) === null || _a === void 0 ? void 0 : _a[0];
if (!capacity) {
console.log('');
throw new Error(`Invalid capacity string: "${textValue}"`);
}
return parseInt(capacity, 10);
},
},
};
//# sourceMappingURL=properties.js.map