Skip to content

Commit

Permalink
add GCal initial
Browse files Browse the repository at this point in the history
  • Loading branch information
egsch committed Nov 22, 2024
1 parent 567bfda commit fd41f05
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 4 deletions.
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,12 @@
}
},
"manifest": {
"oauth2": {
"client_id": "216702397064-tle6n196strafllqdg5541c55p4ovl1q.apps.googleusercontent.com",
"scopes":["openid", "https://www.googleapis.com/auth/calendar.events"]
},
"permissions": [
"identity",
"storage",
"scripting",
"webNavigation",
Expand All @@ -110,5 +115,6 @@
"strict_min_version": "109.0"
}
}
}
},
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1+guFMus8aLnloPa1xMFrElLJFEXOPSA9yjup7L44jCLJfSExjpuwHiKPUmgqKcwg1xhVkeCQiZIppeigc6N22fiwERDaW6xRk2YUsS2qoKbprNMb9SGQ+Q5loIguGGSirTWjp4usq5tRbqD7vTVuouxie6HkjtqI4tS2M4pbabgxL3AFPbCr/T0jYSyIpdlSQoLzFgF1b7UNXjMvkuW1Pt5W5AzeltxhL6Fi7uGk+q6dERf+U3XAjoHdQQWJkNc6gvlNBlxzPFuZ7/6ZdCBU2o5tank1Uwj8txReZrAhnIPZe8Bp3K/M+pHPNCsm+ROD0aDFCtKXoI0eOApbFnW3wIDAQAB"
}
52 changes: 52 additions & 0 deletions src/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
scrapeCourseData,
} from '~content';
import { neededOrigins } from '~data/config';
// import { addGoogleOAuth } from '~popup';

export interface ShowCourseTabPayload {
header: CourseHeader;
Expand All @@ -26,6 +27,9 @@ realBrowser.webNavigation.onHistoryStateUpdated.addListener((details) => {
if (
/^.*:\/\/utdallas\.collegescheduler\.com\/terms\/.*\/courses\/.+$/.test(
details.url,
) ||
/^.*:\/\/utdallas\.collegescheduler\.com\/terms\/.*\/currentschedule$/.test(
details.url,
)
) {
//Scrape data
Expand Down Expand Up @@ -86,6 +90,13 @@ realBrowser.runtime.onMessage.addListener(function (message) {
}
});

realBrowser.runtime.onMessage.addListener(function (message) {
if (message.name === 'insertEventToGoogleCalendar') {
console.log(message.event, message.token);
insertEventToGoogleCalendar(message.event);
}
});

/** Sets the icon to be active if we're on a course tab */
realBrowser.tabs.onActivated.addListener(async () => {
const cachedTabUrl: string = await storage.get('courseTabUrl');
Expand Down Expand Up @@ -132,3 +143,44 @@ async function getCurrentTab() {
const [tab] = await realBrowser.tabs.query(queryOptions);
return tab;
}

export async function insertEventToGoogleCalendar(event) {
console.log('added', event.pid, event.toString());

try {
chrome.identity.getAuthToken(
{
interactive: false,
},
(token) => {
if (!token) {
chrome.identity.clearAllCachedAuthTokens();
chrome.storage.local.set({}, function () {});
}
chrome.storage.local.set({ token: token }, function () {});
const headers = new Headers({
Authorization: 'Bearer ' + token,
'Content-Type': 'application/json',
});

const body = JSON.stringify(event);

fetch(
'https://www.googleapis.com/calendar/v3/calendars/primary/events',
{
method: 'POST',
headers: headers,
body: body,
},
)
.then((response) => response.json())
.then((data) => console.log('Event added:', data))
.catch((error) => {
console.error('Error adding event:', error);
});
},
);
} catch (error) {
console.error(error);
}
}
7 changes: 6 additions & 1 deletion src/components/Landing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import tutorial2 from 'data-base64:../../assets/tutorial2.png';
import React, { useEffect, useState } from 'react';

import { TRENDS_URL } from '~data/config';
import { addGoogleOAuth } from '~popup';

const STORAGE_KEY = 'page';

Expand Down Expand Up @@ -70,6 +71,9 @@ const storage = new Storage({
area: 'local',
});




const Landing = () => {
const [page, setPage] = useState(0);
useEffect(() => {
Expand All @@ -86,7 +90,7 @@ const Landing = () => {
},
});
}, []);

switch (page) {
case 0:
return (
Expand Down Expand Up @@ -135,6 +139,7 @@ const Landing = () => {
>
Get Started
</Button>

</div>
</div>
);
Expand Down
151 changes: 149 additions & 2 deletions src/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ export interface CourseHeader {

// Plasmo CS config export
export const config: PlasmoCSConfig = {
matches: ['https://utdallas.collegescheduler.com/terms/*/courses/*'],
matches: [
'https://utdallas.collegescheduler.com/terms/*/courses/*',
'https://utdallas.collegescheduler.com/terms/*/currentschedule',
],
world: 'MAIN',
};

Expand All @@ -18,6 +21,7 @@ export const config: PlasmoCSConfig = {
* - It injects the instructor names into the section table
*/
export async function scrapeCourseData() {
console.log('scraping course data');
const [header, professors] = await Promise.all([
getCourseInfo(),
injectAndGetProfessorNames(),
Expand Down Expand Up @@ -52,8 +56,8 @@ export async function scrapeCourseData() {

/** Gets all professor names and then injects them into the section table */
async function injectAndGetProfessorNames(): Promise<string[]> {
const courseTable = await waitForElement('table');
const professors: string[] = [];
const courseTable = await waitForElement('table');
const courseRows = courseTable.querySelectorAll('tbody');

// add Professor header to the table
Expand All @@ -62,6 +66,18 @@ export async function scrapeCourseData() {
const line1 = document.createElement('div');
line1.innerText = 'Instructor(s)';
newHeader.append(line1);

chrome.storage.local.get('token', async function (tokenStored) {
console.log(tokenStored);
if (typeof tokenStored.token !== 'undefined') {
// add Save to Skedge
const newHeader2 = document.createElement('th');
const saveLine = document.createElement('div');
line1.innerText = 'Save';
newHeader2.append(saveLine);
tableHeaders.insertBefore(newHeader2, tableHeaders.children[1]);
}
});
// add Skedge reminder
const line2 = document.createElement('div');
line2.style.fontWeight = 'normal';
Expand All @@ -71,6 +87,7 @@ export async function scrapeCourseData() {
tableHeaders.insertBefore(newHeader, tableHeaders.children[7]);

courseRows.forEach((courseRow) => {
console.log('row');
// get professor name from course row
const sectionDetailsButton =
courseRow.querySelector<HTMLButtonElement>('tr > td > button');
Expand All @@ -79,23 +96,153 @@ export async function scrapeCourseData() {
const sectionDetails = courseRow.querySelector('tr:nth-child(2)');
const sectionDetailsList = sectionDetails.querySelectorAll('li');
let professor = '';
let title = '';
sectionDetailsList.forEach((li) => {
const detailLabelText =
li.querySelector<HTMLElement>('strong > span').innerText;
if (detailLabelText.includes('Instructor')) {
professor = li.innerText.split(':')[1].trim();
}
if (detailLabelText.includes('Description')) {
title = li.innerText.split(':')[1].split('(')[0].trim();
}
});
// append professor name to the table
const newTd = document.createElement('td');
newTd.innerText = professor ?? 'No Instructor';
const newButtonTd = document.createElement('td');
const newButton = document.createElement('button');
newButtonTd.appendChild(newButton);
newButton.style.background = '#E98300';
newButton.style.color = '#000';
newButton.style.border = 'none';
newButton.style.borderRadius = '5px';
newButton.style.padding = '10px';
newButton.style.margin = '10px';
newButton.innerText = 'Save';
// this is in case we have multiple instructions per section
const sectionProfessors = professor.split(',');
sectionProfessors.forEach((sectionProfessor) => {
professors.push(sectionProfessor.trim());
});
const courseRowCells = courseRow.querySelector('tr');
const times =
courseRowCells.children[courseRowCells.children.length - 1].textContent;
courseRowCells.insertBefore(newTd, courseRowCells.children[7]);
console.log(title);

const semesters = {
S25: {
firstMonthOfSemester: '01',
firstMondayOfSemester: 21,
lastMonthOfSemester: '05',
lastFridayOfSemester: 15,
},
F25: {
firstMonthOfSemester: '08',
firstMondayOfSemester: 21,
lastMonthOfSemester: '12',
lastFridayOfSemester: 15,
},
};
const semester = semesters.S25;
console.log('semester');

// parse
const monday = semester.firstMondayOfSemester;
const tuesday = semester.firstMondayOfSemester + 1;
const wednesday = semester.firstMondayOfSemester + 2;

let day1 = null;
let day2 = null;
const splitTimes = times.split(' ');
if (splitTimes[0] == 'MW') {
day1 = monday;
day2 = wednesday;
} else if (splitTimes[0] == 'TTh') {
day1 = tuesday;
day2 += tuesday + 2;
} else if (splitTimes[0] == 'F') {
day1 = wednesday + 2;
} else if (splitTimes[0] == 'W') {
day1 = wednesday;
}
let startTime = splitTimes[1].replace('am', '');
let endTime = splitTimes[3].replace('am', '');
if (startTime.includes('pm')) {
startTime = startTime.replace('pm', '');
const startTimeNum = Number(startTime.split(':')[0]);
startTime =
(
Number(startTime.split(':')[0]) + (startTimeNum !== 12 ? 12 : 0)
).toString() +
':' +
startTime.split(':')[1];
}
if (endTime.includes('pm')) {
endTime = endTime.replace('pm', '');
const endTimeNum = Number(endTime.split(':')[0]);
endTime =
(
Number(endTime.split(':')[0]) + (endTimeNum !== 12 ? 12 : 0)
).toString() +
':' +
endTime.split(':')[1];
}
const event1 = {
summary: title,
organization: 'Class from Skedge',
start: {
dateTime: `2025-${semester.firstMonthOfSemester}-${day1}T${startTime}:00-06:00`,
timeZone: 'America/Chicago',
},
end: {
dateTime: `2025-${semester.firstMonthOfSemester}-${day1}T${endTime}:00-06:00`,
timeZone: 'America/Chicago',
},
recurrence: [
`RRULE:FREQ=WEEKLY;UNTIL=2025${semester.lastMonthOfSemester}${semester.lastFridayOfSemester}T170000Z`,
],
pid: 0,
};
const event2 = {
summary: title,
organization: 'Class from Skedge',
start: {
dateTime: `2025-${semester.firstMonthOfSemester}-${day2}T${startTime}:00-06:00`,
timeZone: 'America/Chicago',
},
end: {
dateTime: `2025-${semester.firstMonthOfSemester}-${day2}T${endTime}:00-06:00`,
timeZone: 'America/Chicago',
},
recurrence: [
`RRULE:FREQ=WEEKLY;UNTIL=2025${semester.lastMonthOfSemester}${semester.lastFridayOfSemester}T170000Z`,
],
pid: 0,
};

chrome.storage.local.get('token', async function (tokenStored) {
if (typeof tokenStored.token !== 'undefined') {
newButton.onclick = async () => {
chrome.runtime.sendMessage({
name: 'insertEventToGoogleCalendar',
event: event1,
token: tokenStored.token,
});
if (event2) {
chrome.runtime.sendMessage({
name: 'insertEventToGoogleCalendar',
event: event2,
token: tokenStored.token,
});
}
alert(`Added ${event1.summary} to calendar.`);
};
courseRowCells.insertBefore(newButton, courseRowCells.children[1]);
}
});

//Increase Disabled Reasons row colspan if necessary
const sectionDisabled = courseRow.querySelector(
'tr:nth-child(3) > td',
Expand Down
27 changes: 27 additions & 0 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Button } from '@mui/material';
import { sendToBackground } from '@plasmohq/messaging';
import React, { useEffect, useState } from 'react';

Expand All @@ -13,6 +14,7 @@ import fetchWithCache, {
cacheIndexGrades,
expireTime,
} from '~data/fetchWithCache';
import { addGoogleOAuth } from '~popup';
import {
convertToProfOnly,
type SearchQuery,
Expand Down Expand Up @@ -175,6 +177,19 @@ function removeDuplicates(array: SearchQuery[]) {

const Index = () => {
const [page, setPage] = useState<'landing' | 'list' | SearchQuery>('landing');
const [isSignedIn, setIsSignedIn] = useState(false);
useEffect(() => {
if (process.env.PLASMO_BROWSER === 'chrome') {
chrome.storage.local.get('token', (tokenStored) => {
if (!tokenStored.token) {
setIsSignedIn(false);
} else {
console.log(tokenStored.token);
setIsSignedIn(true);
}
});
}
});
const [listScroll, setListScroll] = useState(0);
function setPageAndScroll(set: 'landing' | 'list' | SearchQuery) {
if (set === 'list') {
Expand Down Expand Up @@ -328,6 +343,18 @@ const Index = () => {
rmp={rmp}
setPage={setPageAndScroll}
/>
{(process.env.PLASMO_BROWSER === 'chrome' && !isSignedIn) && (
<Button
variant="contained"
disableElevation
size="large"
className="normal-case bg-royal hover:bg-royalDark"
onClick={addGoogleOAuth}
>
Optional: Enable Google Calendar to add your classes with the
press of a button
</Button>)
}
</div>
{page !== 'list' && (
<div className="h-fit min-h-full p-4 dark:bg-black">
Expand Down
Loading

0 comments on commit fd41f05

Please sign in to comment.