-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathfetch.ts
115 lines (92 loc) · 3.95 KB
/
fetch.ts
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
import moment from 'moment-timezone';
import { CanvasClient } from '../apis/canvas';
import { Storage } from '../apis/storage';
import { EmojiRequest } from '../types/notion';
export interface IFetchedAssignment {
name: string;
description: string | null;
points: number;
course: string;
icon: EmojiRequest | null;
url: string;
available: string | null;
due: string | null;
}
export interface SavedAssignments {
[course: string]: IFetchedAssignment[];
}
function roundToNextHour(date: Date): Date {
if (date.getMinutes() === 0) return date;
date.setHours(date.getHours() + 1, 0, 0, 0);
return date;
}
function reformatDate(dateString: string | null, timeZone: string | null): string | null {
if (!dateString) return null;
/*
Problem: Notion does not convert times into the correct timezone,
even when supplied a timezone, Notion will show the user the
UTC time (incorrect time, unless you live in UTC region), labeled
with the supplied timezone.
Solution: Re-format the ISO date string to give Notion a 'false' date string based
on the timezone provided by the user. This is a misuse of ISO time/date strings,
but it will result in the correct date being shown in Notion.
*/
const date = new Date(dateString);
const offset = moment.tz.zone(timeZone ?? moment.tz.guess())?.utcOffset(date.valueOf()) ?? 0;
date.setMinutes(date.getMinutes() - offset);
return date.toISOString();
}
(async function fetchAssignments(): Promise<SavedAssignments | void> {
try {
const { origin, pathname } = window.location;
const courseId = pathname.match(/\/courses\/([^/]+)\/?/)?.[1];
if (!courseId) {
throw 'This is an invalid Canvas course page.\n\nPlease navigate to a Canvas course page (or any subpage), and try again.\n\nExample: https://canvas.auckland.ac.nz/courses/72763/...';
}
const canvasClient = new CanvasClient({ origin, courseId });
const [course, assignmentGroups] = await Promise.all([
canvasClient.fetchCourse(),
canvasClient.fetchAssignmentGroups(),
]);
if (!course || !assignmentGroups) {
throw `Failed to fetch ${(!course) ? 'course' : 'assignments'}.\n\nPlease try again later.\n\nIf this issue persists, please open an Issue on GitHub or report it in the Discord Server.`;
}
const options = await Storage.getOptions();
const courseCode = options.canvas.courseCodeOverrides[course.course_code] ?? course.course_code;
const courseIcon = options.notion.courseEmojis[courseCode] ?? null;
const emojiedCourseCode = `${(courseIcon) ? `${courseIcon} ` : ''}${courseCode}`;
const timeNow = new Date();
const canvasAssignments = assignmentGroups.flatMap(group => group.assignments)
.filter(assignment => options.canvas.importMissingDueDates || assignment.due_at)
.sort(({ due_at: a }, { due_at: b }) => {
return Date.parse(a ?? timeNow.toISOString()) - Date.parse(b ?? timeNow.toISOString());
})
.map(assignment => ({
name: assignment.name,
description: assignment.description,
points: assignment.points_possible,
course: courseCode,
icon: courseIcon,
url: assignment.html_url,
available: (assignment.unlock_at)
? reformatDate(assignment.unlock_at, options.notion.timeZone)
// If the due date is in the past, set the available date to be one month before that.
// See #388.
: (assignment.due_at && (timeNow < new Date(assignment.due_at)))
? reformatDate(roundToNextHour(timeNow).toISOString(), options.notion.timeZone)
: reformatDate(moment(assignment.due_at ?? 0).subtract(1, 'month').format(), options.notion.timeZone),
due: reformatDate(assignment.due_at, options.notion.timeZone),
}));
const savedAssignments = await Storage.getSavedAssignments();
savedAssignments[emojiedCourseCode] = canvasAssignments;
await Promise.all([
Storage.setSavedAssignments(savedAssignments),
Storage.setSavedCourse(emojiedCourseCode),
]);
return savedAssignments;
}
catch (error) {
alert(error);
return Storage.setSavedCourse(null);
}
})();