-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrefresh.js
163 lines (151 loc) · 6.09 KB
/
refresh.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#!/usr/bin/env node
// imports
const fs = require('fs');
const bent = require('bent');
const prettyMs = require('pretty-ms');
const { getSeasonFromFile } = require('./seasonFromFile.js');
const admin = require('firebase-admin');
var serviceAccount = require("/root/rct-backend/rutgers-course-tracker-firebase-adminsdk-7pvr2-00983f5cf0.json")
const app = admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://rutgers-course-tracker.firebaseio.com/'
});
// constants
const DEBUG = true;
const baseSubjectsURI = "https://sis.rutgers.edu/oldsoc/subjects.json";
const baseCoursesURI = "http://sis.rutgers.edu/oldsoc/courses.json";
const getJSON = bent('json');
const seasonInt = {
0: 'winter',
1: 'spring',
7: 'summer',
9: 'fall'
}
// functions
// returns a new object with the values at each key mapped using mapFn(value)
function objectMap(object, mapFn) {
return Object.keys(object).reduce(function(result, key) {
result[key] = mapFn(object[key]);
return result;
}, {})
}
// main function for updating firestore
async function firestoreCourseData( db ) {
// variable for checking how long this took
const before = Date.now();
// figure out what season and year we're in
const date = new Date();
const querySeason = getSeasonFromFile('season.txt');
const year = date.getFullYear();
// if fall query fall and summer, if spring query spring and winter
const seasons = querySeason == "fall" ? [9, 7] : [1, 0];
// get subjects from SOC
const subjectRequestArr = seasons.map(season => {
const isSpring = season == 1; // if the season is spring we need to increment year
const requestURI = `${baseSubjectsURI}?semester=${season}${year + (isSpring ? 1 : 0)}&campus=NB&level=U`;
console.log(`Requesting URI: ${requestURI}`);
return getJSON(requestURI);
});
let subjectList;
try {
subjectList = (await Promise.all(subjectRequestArr))[0];
} catch( e ) {
console.error( "SOC API Connection error:", e );
process.exit();
}
// get courses from SOC
const courseRequestArr = [];
subjectList.forEach(subject => {
seasons.forEach(season => {
const isSpring = season == 1; // if the season is spring we need to increment year
const requestURI = `${baseCoursesURI}?subject=${subject.code}&semester=${season}${year + (isSpring ? 1 : 0)}&campus=NB&level=UG`;
console.log(`Requesting URI: ${requestURI}`);
courseRequestArr.push({
promise: getJSON(requestURI),
season: seasonInt[season]
});
})
})
console.log("Finished collecting all courses. Attempting to resolve all of them.");
let subjects = await Promise.all(courseRequestArr.map(rObj => rObj.promise));
if( !subjects ) {
console.error("No subjects could be found.");
process.exit();
}
// construct maps for insertion into firestore
let indexMap = {};
subjects.forEach( (subject,idx) => {
subject.forEach(course => {
if( !course.sections ) {
console.warn(`Course ${course.title}: ${course.courseNumber} sections were not found. Skipping...`);
return;
}
course.sections.forEach( section => {
if( !course.subject || !course.title || !section.number || !section.index ) {
console.warn(`One or more fields were missing for course ${course.title}, section index ${section.index}, course subject ${course.subject}, section number ${section.number}. Skipping...`);
return;
}
// construct maps
if( !indexMap[courseRequestArr[idx].season] ) indexMap[courseRequestArr[idx].season] = {};
indexMap[courseRequestArr[idx].season][section.index] = {
subject: course.subject,
name: course.title,
section: section.number,
course: course.courseNumber
};
});
});
});
// write data from maps to firestore
for( const season in indexMap ) {
console.log(`Writing data to season ${season}:`, indexMap[season]);
// get appropriate season doc
const seasonColl = db
.collection(season)
// set sections
seasonColl
.doc("sections")
.set({
sections: objectMap(indexMap[season], value => value.section)
})
.then( writeData => {
if( DEBUG ) console.log("Wrote sections to firestore successfully:", writeData);
})
.catch(err => console.error('Error setting document:', err));
// set names
seasonColl
.doc("names")
.set({
names: objectMap(indexMap[season], value => value.name)
})
.then( writeData => {
if( DEBUG ) console.log("Wrote names to firestore successfully:", writeData);
})
.catch(err => console.error('Error setting document:', err));
// set subjects
seasonColl
.doc("subjects")
.set({
subjects: objectMap(indexMap[season], value => value.subject)
})
.then( writeData => {
if( DEBUG ) console.log("Wrote subjects to firestore successfully:", writeData);
})
.catch(err => console.error('Error setting document:', err));
// set course numbers
seasonColl
.doc("courses")
.set({
courses: objectMap(indexMap[season], value => value.course)
})
.then( writeData => {
if( DEBUG ) console.log("Wrote course numbers to firestore successfully:", writeData);
})
.catch(err => console.error('Error setting document:', err));
}
// print out how long it took
const after = Date.now();
console.log(`Operation completed in ${prettyMs(after-before)}.`);
}
// run
firestoreCourseData( admin.firestore() );