Skip to content

Instantly share code, notes, and snippets.

@qazxcdswe123
Created August 23, 2022 12:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qazxcdswe123/89c37e21809c6619ae62255fcfd9130d to your computer and use it in GitHub Desktop.
Save qazxcdswe123/89c37e21809c6619ae62255fcfd9130d to your computer and use it in GitHub Desktop.
ICS File Generator for SCNU Student to Use in Calendar App

ICS File Generator for SCNU Student

Author: YnChen

Contact: i at ynchen dot me

How To Use

  1. Install NodeJS
  2. Run npm i -S ics
  3. Get your course data from SCNU 教务系统 -> 信息查询 -> 学生课表查询
  4. Open Developer Tools -> Network -> Refresh the page -> Find xskbcx_cxXsgrkb.html
  5. Paste the Response into data.json
  6. Customize config.json
  7. Run node main.js
  8. The output.ics is your calendar file, you can now import it into your favourite calendar app
{
"alertMinutesBeforeClassStart": 18,
"semesterStartDate": "2022-08-29"
}
// remember to customize in config.json
// also remember to npm i -S ics
"use strict";
const { writeFileSync, readFileSync } = require("fs");
const { createEvents } = require("ics");
const rawData = readFileSync("data.json");
const configFile = readFileSync("config.json");
// format:
// key = the index of class
// value = array[start, end]
const classNumberToTimeMapping = {
1: ["08:30", "09:10"],
2: ["09:20", "10:00"],
3: ["10:20", "11:00"],
4: ["11:10", "11:50"],
5: ["14:30", "15:10"],
6: ["15:20", "16:00"],
7: ["16:10", "16:50"],
8: ["17:00", "17:40"],
9: ["19:00", "19:40"],
10: ["19:50", "20:30"],
};
// let startDate = new Date(2022, 7, 29, 0, 0);
const alertMinutesBeforeClassStart = parseInt(
JSON.parse(configFile).alertMinutesBeforeClassStart
);
const startDate = new Date(JSON.parse(configFile).semesterStartDate);
// kbList is the array of classes
const data = JSON.parse(rawData).kbList;
let alarm = [
{
action: "display",
trigger: { minutes: alertMinutesBeforeClassStart, before: true },
},
];
// data.cdmc is the location of classroom (set in ics description)
// data.kcmc is the name of class (set as event title)
// data.xm is the teacher (set in ics description)
// data.zcd is the duration time of the class (x-y周)
// data.jcs is the index of the class (x-y), use classNumberToTimeMapping to get the time
// data.xqj is the day of the week (1-7)
let events = [];
function addEvent() {
for (let i = 0; i < data.length; i++) {
// collect class info
const classData = data[i];
const classStartWeek = parseInt(classData.zcd.split("-")[0]);
const classEndWeek = parseInt(classData.zcd.split("-")[1]);
const classStartTime =
classNumberToTimeMapping[classData.jcs.split("-")[0]][0];
const classEndTime =
classNumberToTimeMapping[classData.jcs.split("-")[1]][1];
// begin ics info
let start = new Date(startDate);
start.setDate(
start.getDate() +
parseInt(classData.xqj) +
7 * (classStartWeek - 1) -
1
);
start.setHours(parseInt(classStartTime.split(":")[0]));
start.setMinutes(parseInt(classStartTime.split(":")[1]));
let end = new Date(start);
end.setHours(parseInt(classEndTime.split(":")[0]));
end.setMinutes(parseInt(classEndTime.split(":")[1]));
const title = classData.kcmc;
const description = `教师: ${classData.xm}`;
const count = classEndWeek - classStartWeek + 1;
const startArray = [
start.getFullYear(),
start.getMonth() + 1,
start.getDate(),
start.getHours(),
start.getMinutes(),
];
const endArray = [
end.getFullYear(),
end.getMonth() + 1,
end.getDate(),
end.getHours(),
end.getMinutes(),
];
const location = classData.cdmc;
// add event
events.push({
title: title,
description: description,
start: startArray,
end: endArray,
recurrenceRule: "FREQ=WEEKLY;COUNT=" + count,
alarms: alarm,
location: location,
});
}
// generate ics file
createEvents(events, (error, value) => {
if (error) {
console.log(error);
return;
}
console.log(value);
writeFileSync("output.ics", value);
});
}
addEvent();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment