mirror of
https://github.com/Xevion/schedule-extract.git
synced 2025-12-09 10:08:35 -06:00
Webpack, manifest, build progress
This commit is contained in:
1
src/index.ts
Normal file
1
src/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
console.log("Hello world!")
|
||||
27
src/manifestFirefox.json
Normal file
27
src/manifestFirefox.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Class Schedule ICS",
|
||||
"version": "X.Y.Z",
|
||||
"description": "Adds a button to the UTSA class schedule to download an ICS file for the selected classes.",
|
||||
"icons": {
|
||||
"32": "svg/icon.svg",
|
||||
"48": "svg/icon.svg",
|
||||
"64": "svg/icon.svg",
|
||||
"96": "svg/icon.svg"
|
||||
},
|
||||
"permissions": [
|
||||
"https://ssbprod.utsa.edu/StudentRegistrationSsb/ssb/*"
|
||||
],
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": [
|
||||
"https://ssbprod.utsa.edu/StudentRegistrationSsb/ssb/*"
|
||||
],
|
||||
"js": [
|
||||
"main.js"
|
||||
],
|
||||
"css": [
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
105
src/old.ts
Normal file
105
src/old.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import {Cheerio, Element, load} from "cheerio";
|
||||
import {readFileSync} from "fs";
|
||||
import {parse} from "date-fns";
|
||||
import {inspect} from "util";
|
||||
import {decode} from "html-entities";
|
||||
import fetch from "node-fetch";
|
||||
import {z} from "zod";
|
||||
|
||||
const $ = load(readFileSync('list.html'));
|
||||
const classes = $('#scheduleListView').children('.listViewWrapper');
|
||||
|
||||
const name_pattern = /(.+) (\d{4}) Section (\d+)/;
|
||||
|
||||
const subject_schema = z.object({
|
||||
code: z.string(),
|
||||
description: z.string().transform((v) => decode(v, {level: 'all'})),
|
||||
});
|
||||
|
||||
type Subject = z.infer<typeof subject_schema>;
|
||||
|
||||
|
||||
const subjects = await z.array(subject_schema).parseAsync(
|
||||
await fetch(
|
||||
'https://ssbprod.utsa.edu/StudentRegistrationSsb/ssb/classSearch/get_subject' + '?' + new URLSearchParams({
|
||||
"searchTerm": "",
|
||||
"term": "202410",
|
||||
"offset": "1",
|
||||
"max": "999"
|
||||
})
|
||||
).then((response) => {
|
||||
return response.json();
|
||||
})
|
||||
);
|
||||
|
||||
const subject_by_name = new Map(subjects.map((subject) => [subject.description, subject]));
|
||||
|
||||
|
||||
function getOffset(period: string) {
|
||||
switch (period) {
|
||||
case "AM":
|
||||
return 0;
|
||||
case "PM":
|
||||
return 12;
|
||||
default:
|
||||
throw new Error(`Unknown period: ${period}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function extractDetails(source: Cheerio<Element>) {
|
||||
const details: [string, string][] = source.find('div.list-view-crn-info-div > span.bold').toArray().map((descriptor) => {
|
||||
const descriptor_element = $(descriptor);
|
||||
return [descriptor_element.text(), descriptor_element.next().text()]
|
||||
})
|
||||
|
||||
const timing_information = source.find('div.list-view-pillbox.ui-pillbox').next();
|
||||
|
||||
const raw_time = timing_information.text();
|
||||
const match = raw_time.match(/(\d{2})\s*:\s*(\d{2})\s*(AM|PM)\D*(\d{2})\s*:\s*(\d{2})\s*(AM|PM)/)
|
||||
if (match === null) {
|
||||
throw new Error(`Could not parse time: ${raw_time}`);
|
||||
}
|
||||
|
||||
const [start_hour, start_minute, end_hour, end_minute] = [1, 2, 4, 5].map((index) => parseInt(match[index]));
|
||||
const [start_period, end_period] = [match[3], match[6]];
|
||||
|
||||
const raw_date = source.find('span.meetingTimes').text();
|
||||
const [start_date, end_date] = raw_date.split("--").map((date) => parse(date.trim(), "MM/dd/yyyy", new Date()));
|
||||
|
||||
const identifier = source.find('span.list-view-subj-course-section').text();
|
||||
const name_match = name_pattern.exec(identifier);
|
||||
if (name_match === null) {
|
||||
throw new Error(`Could not parse identifier: ${identifier}`);
|
||||
}
|
||||
|
||||
const [subject_name, code, section] = name_match.slice(1);
|
||||
const subject = subject_by_name.get(subject_name);
|
||||
if (subject === undefined) {
|
||||
throw new Error(`Unknown subject: ${subject_name}`);
|
||||
}
|
||||
|
||||
return {
|
||||
identifier: {
|
||||
subject,
|
||||
code: code,
|
||||
section: section,
|
||||
crn: null,
|
||||
},
|
||||
date: {
|
||||
start: start_date,
|
||||
end: end_date,
|
||||
},
|
||||
time: {
|
||||
start: {minute: start_minute, hour: start_hour + getOffset(start_period)},
|
||||
end: {minute: end_minute, hour: end_hour + getOffset(end_period)},
|
||||
},
|
||||
days: source.find('div.ui-pillbox-summary.screen-reader').text().split(",").map((day) => day.trim()),
|
||||
name: source.find('span.list-view-course-title > a.section-details-link').text().trim()
|
||||
};
|
||||
}
|
||||
|
||||
console.log(`${classes.length} classes identified.`);
|
||||
console.log(
|
||||
inspect(classes.toArray().map((element) => extractDetails($(element))), {colors: true, depth: null})
|
||||
);
|
||||
Reference in New Issue
Block a user