@robertying/thu-learn-lib 0.0.0-stage → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +324 -2
- package/lib/auth.d.ts +11 -0
- package/lib/auth.d.ts.map +1 -0
- package/lib/auth.js +99 -0
- package/lib/auth.js.map +1 -0
- package/lib/calendar.d.ts +16 -0
- package/lib/calendar.d.ts.map +1 -0
- package/lib/calendar.js +81 -0
- package/lib/calendar.js.map +1 -0
- package/lib/contents.d.ts +9 -0
- package/lib/contents.d.ts.map +1 -0
- package/lib/contents.js +51 -0
- package/lib/contents.js.map +1 -0
- package/lib/courses.d.ts +11 -0
- package/lib/courses.d.ts.map +1 -0
- package/lib/courses.js +94 -0
- package/lib/courses.js.map +1 -0
- package/lib/discussions.d.ts +11 -0
- package/lib/discussions.d.ts.map +1 -0
- package/lib/discussions.js +56 -0
- package/lib/discussions.js.map +1 -0
- package/lib/favorites.d.ts +35 -0
- package/lib/favorites.d.ts.map +1 -0
- package/lib/favorites.js +150 -0
- package/lib/favorites.js.map +1 -0
- package/lib/files.d.ts +13 -0
- package/lib/files.d.ts.map +1 -0
- package/lib/files.js +167 -0
- package/lib/files.js.map +1 -0
- package/lib/homework.d.ts +17 -0
- package/lib/homework.d.ts.map +1 -0
- package/lib/homework.js +194 -0
- package/lib/homework.js.map +1 -0
- package/lib/index.d.ts +134 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +219 -0
- package/lib/index.js.map +1 -0
- package/lib/notices.d.ts +14 -0
- package/lib/notices.d.ts.map +1 -0
- package/lib/notices.js +92 -0
- package/lib/notices.js.map +1 -0
- package/lib/questionnaires.d.ts +7 -0
- package/lib/questionnaires.d.ts.map +1 -0
- package/lib/questionnaires.js +62 -0
- package/lib/questionnaires.js.map +1 -0
- package/lib/request.d.ts +57 -0
- package/lib/request.d.ts.map +1 -0
- package/lib/request.js +197 -0
- package/lib/request.js.map +1 -0
- package/lib/types.d.ts +433 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +98 -0
- package/lib/types.js.map +1 -0
- package/lib/urls.d.ts +78 -0
- package/lib/urls.d.ts.map +1 -0
- package/lib/urls.js +160 -0
- package/lib/urls.js.map +1 -0
- package/lib/user.d.ts +7 -0
- package/lib/user.d.ts.map +1 -0
- package/lib/user.js +22 -0
- package/lib/user.js.map +1 -0
- package/lib/utils.d.ts +16 -0
- package/lib/utils.d.ts.map +1 -0
- package/lib/utils.js +117 -0
- package/lib/utils.js.map +1 -0
- package/package.json +67 -4
- package/src/auth.ts +121 -0
- package/src/calendar.ts +102 -0
- package/src/contents.ts +63 -0
- package/src/courses.ts +111 -0
- package/src/discussions.ts +80 -0
- package/src/favorites.ts +167 -0
- package/src/files.ts +197 -0
- package/src/homework.ts +284 -0
- package/src/index.ts +345 -0
- package/src/notices.ts +115 -0
- package/src/questionnaires.ts +76 -0
- package/src/request.ts +214 -0
- package/src/types.ts +494 -0
- package/src/urls.ts +257 -0
- package/src/user.ts +28 -0
- package/src/utils.ts +125 -0
package/src/urls.ts
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { FormData } from 'node-fetch-native';
|
|
2
|
+
import type { ContentType, IHomeworkSubmitAttachment, QuestionnaireType } from './types.ts';
|
|
3
|
+
import { CourseType, Language } from './types.ts';
|
|
4
|
+
import { CONTENT_TYPE_MAP, getMkFromType } from './utils.ts';
|
|
5
|
+
|
|
6
|
+
export const ID_PREFIX = 'https://id.tsinghua.edu.cn';
|
|
7
|
+
export const LEARN_PREFIX = 'https://learn.tsinghua.edu.cn';
|
|
8
|
+
export const REGISTRAR_PREFIX = 'https://zhjw.cic.tsinghua.edu.cn';
|
|
9
|
+
|
|
10
|
+
const MAX_SIZE = 200;
|
|
11
|
+
|
|
12
|
+
export const ID_LOGIN = () => 'https://id.tsinghua.edu.cn/do/off/ui/auth/login/form/bb5df85216504820be7bba2b0ae1535b/0';
|
|
13
|
+
|
|
14
|
+
export const ID_LOGIN_CHECK = () => 'https://id.tsinghua.edu.cn/do/off/ui/auth/login/check';
|
|
15
|
+
|
|
16
|
+
export const LEARN_AUTH_ROAM = (ticket: string) =>
|
|
17
|
+
`${LEARN_PREFIX}/b/j_spring_security_thauth_roaming_entry?ticket=${ticket}`;
|
|
18
|
+
|
|
19
|
+
export const LEARN_LOGOUT = () => `${LEARN_PREFIX}/f/j_spring_security_logout`;
|
|
20
|
+
|
|
21
|
+
export const LEARN_HOMEPAGE = (courseType: CourseType) => {
|
|
22
|
+
if (courseType === CourseType.STUDENT) {
|
|
23
|
+
return `${LEARN_PREFIX}/f/wlxt/index/course/student/`;
|
|
24
|
+
} else {
|
|
25
|
+
return `${LEARN_PREFIX}/f/wlxt/index/course/teacher/`;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const LEARN_STUDENT_COURSE_LIST_PAGE = () => `${LEARN_PREFIX}/f/wlxt/index/course/student/`;
|
|
30
|
+
|
|
31
|
+
export const LEARN_SEMESTER_LIST = () => `${LEARN_PREFIX}/b/wlxt/kc/v_wlkc_xs_xktjb_coassb/queryxnxq`;
|
|
32
|
+
|
|
33
|
+
export const LEARN_CURRENT_SEMESTER = () => `${LEARN_PREFIX}/b/kc/zhjw_v_code_xnxq/getCurrentAndNextSemester`;
|
|
34
|
+
|
|
35
|
+
export const LEARN_COURSE_LIST = (semester: string, courseType: CourseType, lang: Language) =>
|
|
36
|
+
courseType === CourseType.STUDENT
|
|
37
|
+
? `${LEARN_PREFIX}/b/wlxt/kc/v_wlkc_xs_xkb_kcb_extend/student/loadCourseBySemesterId/${semester}/${lang}`
|
|
38
|
+
: `${LEARN_PREFIX}/b/kc/v_wlkc_kcb/queryAsorCoCourseList/${semester}/0`;
|
|
39
|
+
|
|
40
|
+
export const LEARN_COURSE_PAGE = (courseID: string, courseType: CourseType) =>
|
|
41
|
+
`${LEARN_PREFIX}/f/wlxt/index/course/${courseType}/course?wlkcid=${courseID}`;
|
|
42
|
+
|
|
43
|
+
export const LEARN_COURSE_TIME_LOCATION = (courseID: string) =>
|
|
44
|
+
`${LEARN_PREFIX}/b/kc/v_wlkc_xk_sjddb/detail?id=${courseID}`;
|
|
45
|
+
|
|
46
|
+
export const LEARN_FILE_LIST = (courseID: string, courseType: CourseType) =>
|
|
47
|
+
courseType === CourseType.STUDENT
|
|
48
|
+
? `${LEARN_PREFIX}/b/wlxt/kj/wlkc_kjxxb/student/kjxxbByWlkcidAndSizeForStudent?wlkcid=${courseID}&size=${MAX_SIZE}`
|
|
49
|
+
: `${LEARN_PREFIX}/b/wlxt/kj/v_kjxxb_wjwjb/teacher/queryByWlkcid?wlkcid=${courseID}&size=${MAX_SIZE}`;
|
|
50
|
+
|
|
51
|
+
export const LEARN_FILE_CATEGORY_LIST = (courseID: string, courseType: CourseType) =>
|
|
52
|
+
`${LEARN_PREFIX}/b/wlxt/kj/wlkc_kjflb/${courseType}/pageList?wlkcid=${courseID}`;
|
|
53
|
+
|
|
54
|
+
export const LEARN_FILE_LIST_BY_CATEGORY_STUDENT = (courseID: string, categoryId: string) =>
|
|
55
|
+
`${LEARN_PREFIX}/b/wlxt/kj/wlkc_kjxxb/student/kjxxb/${courseID}/${categoryId}`;
|
|
56
|
+
|
|
57
|
+
export const LEARN_FILE_LIST_BY_CATEGORY_TEACHER = `${LEARN_PREFIX}/b/wlxt/kj/v_kjxxb_wjwjb/teacher/pageList`;
|
|
58
|
+
|
|
59
|
+
export const LEARN_FILE_LIST_BY_CATEGORY_TEACHER_FORM_DATA = (courseID: string, categoryId: string) => {
|
|
60
|
+
const form = new FormData();
|
|
61
|
+
form.append(
|
|
62
|
+
'aoData',
|
|
63
|
+
JSON.stringify([
|
|
64
|
+
{ name: 'wlkcid', value: courseID },
|
|
65
|
+
{ name: 'kjflid', value: categoryId },
|
|
66
|
+
]),
|
|
67
|
+
);
|
|
68
|
+
return form;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const LEARN_FILE_DOWNLOAD = (fileID: string, courseType: CourseType) =>
|
|
72
|
+
`${LEARN_PREFIX}/b/wlxt/kj/wlkc_kjxxb/${courseType}/downloadFile?sfgk=0&wjid=${fileID}`;
|
|
73
|
+
|
|
74
|
+
export const LEARN_FILE_PREVIEW = (type: ContentType, fileID: string, courseType: CourseType, firstPageOnly = false) =>
|
|
75
|
+
`${LEARN_PREFIX}/f/wlxt/kc/wj_wjb/${courseType}/beforePlay?wjid=${fileID}&mk=${getMkFromType(
|
|
76
|
+
type,
|
|
77
|
+
)}&browser=-1&sfgk=0&pageType=${firstPageOnly ? 'first' : 'all'}`;
|
|
78
|
+
|
|
79
|
+
export const LEARN_NOTIFICATION_LIST = (courseType: CourseType, expired: boolean) =>
|
|
80
|
+
`${LEARN_PREFIX}/b/wlxt/kcgg/wlkc_ggb/` +
|
|
81
|
+
(courseType === CourseType.STUDENT ? 'student/pageListXsby' : 'teacher/pageListby') +
|
|
82
|
+
(expired ? 'Ygq' : 'Wgq');
|
|
83
|
+
|
|
84
|
+
export const LEARN_NOTIFICATION_DETAIL = (courseID: string, notificationID: string, courseType: CourseType) =>
|
|
85
|
+
courseType === CourseType.STUDENT
|
|
86
|
+
? `${LEARN_PREFIX}/f/wlxt/kcgg/wlkc_ggb/student/beforeViewXs?wlkcid=${courseID}&id=${notificationID}`
|
|
87
|
+
: `${LEARN_PREFIX}/f/wlxt/kcgg/wlkc_ggb/teacher/beforeViewJs?wlkcid=${courseID}&id=${notificationID}`;
|
|
88
|
+
|
|
89
|
+
export const LEARN_NOTIFICATION_EDIT = (courseType: CourseType): string =>
|
|
90
|
+
`${LEARN_PREFIX}/b/wlxt/kcgg/wlkc_ggb/${courseType}/editKcgg`;
|
|
91
|
+
|
|
92
|
+
export const LEARN_HOMEWORK_LIST_NEW = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/zyListWj`;
|
|
93
|
+
export const LEARN_HOMEWORK_LIST_SUBMITTED = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/zyListYjwg`;
|
|
94
|
+
export const LEARN_HOMEWORK_LIST_GRADED = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/zyListYpg`;
|
|
95
|
+
export const LEARN_HOMEWORK_LIST_EXCELLENT = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/yxzylist`;
|
|
96
|
+
export const LEARN_HOMEWORK_LIST_SOURCE = [
|
|
97
|
+
{
|
|
98
|
+
url: LEARN_HOMEWORK_LIST_NEW,
|
|
99
|
+
status: {
|
|
100
|
+
submitted: false,
|
|
101
|
+
graded: false,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
url: LEARN_HOMEWORK_LIST_SUBMITTED,
|
|
106
|
+
status: {
|
|
107
|
+
submitted: true,
|
|
108
|
+
graded: false,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
url: LEARN_HOMEWORK_LIST_GRADED,
|
|
113
|
+
status: {
|
|
114
|
+
submitted: true,
|
|
115
|
+
graded: true,
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
export const LEARN_HOMEWORK_PAGE = (courseID: string, id: string) =>
|
|
121
|
+
`${LEARN_PREFIX}/f/wlxt/kczy/zy/student/viewCj?wlkcid=${courseID}&xszyid=${id}`;
|
|
122
|
+
|
|
123
|
+
export const LEARN_HOMEWORK_EXCELLENT_PAGE = (courseID: string, id: string) =>
|
|
124
|
+
`${LEARN_PREFIX}/f/wlxt/kczy/zy/student/viewYxzy?wlkcid=${courseID}&xszyid=${id}`;
|
|
125
|
+
|
|
126
|
+
export const LEARN_HOMEWORK_DETAIL = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/detail`;
|
|
127
|
+
|
|
128
|
+
export const LEARN_HOMEWORK_DETAIL_FORM_DATA = (baseId: string) => {
|
|
129
|
+
const form = new FormData();
|
|
130
|
+
form.append('id', baseId);
|
|
131
|
+
return form;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const LEARN_HOMEWORK_DOWNLOAD = (courseID: string, attachmentID: string) =>
|
|
135
|
+
`${LEARN_PREFIX}/b/wlxt/kczy/zy/student/downloadFile/${courseID}/${attachmentID}`;
|
|
136
|
+
|
|
137
|
+
export const LEARN_HOMEWORK_SUBMIT_PAGE = (courseID: string, id: string) =>
|
|
138
|
+
`${LEARN_PREFIX}/f/wlxt/kczy/zy/student/tijiao?wlkcid=${courseID}&xszyid=${id}`;
|
|
139
|
+
|
|
140
|
+
export const LEARN_HOMEWORK_SUBMIT = () => `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/tjzy`;
|
|
141
|
+
|
|
142
|
+
export const LEARN_HOMEWORK_SUBMIT_FORM_DATA = (
|
|
143
|
+
id: string,
|
|
144
|
+
content = '',
|
|
145
|
+
attachment?: IHomeworkSubmitAttachment,
|
|
146
|
+
removeAttachment = false,
|
|
147
|
+
) => {
|
|
148
|
+
const form = new FormData();
|
|
149
|
+
form.append('xszyid', id);
|
|
150
|
+
form.append('zynr', content ?? '');
|
|
151
|
+
if (attachment) form.append('fileupload', attachment.content, attachment.filename);
|
|
152
|
+
else form.append('fileupload', 'undefined');
|
|
153
|
+
if (removeAttachment) form.append('isDeleted', '1');
|
|
154
|
+
else form.append('isDeleted', '0');
|
|
155
|
+
return form;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export const LEARN_HOMEWORK_LIST_TEACHER = `${LEARN_PREFIX}/b/wlxt/kczy/zy/teacher/pageList`;
|
|
159
|
+
|
|
160
|
+
export const LEARN_HOMEWORK_DETAIL_TEACHER = (courseID: string, homeworkID: string) =>
|
|
161
|
+
`${LEARN_PREFIX}/f/wlxt/kczy/xszy/teacher/beforePageList?zyid=${homeworkID}&wlkcid=${courseID}`;
|
|
162
|
+
|
|
163
|
+
export const LEARN_DISCUSSION_LIST = (courseID: string, courseType: CourseType) =>
|
|
164
|
+
`${LEARN_PREFIX}/b/wlxt/bbs/bbs_tltb/${courseType}/kctlList?wlkcid=${courseID}&size=${MAX_SIZE}`;
|
|
165
|
+
|
|
166
|
+
export const LEARN_DISCUSSION_DETAIL = (
|
|
167
|
+
courseID: string,
|
|
168
|
+
boardID: string,
|
|
169
|
+
discussionID: string,
|
|
170
|
+
courseType: CourseType,
|
|
171
|
+
tabId = 1,
|
|
172
|
+
) =>
|
|
173
|
+
`${LEARN_PREFIX}/f/wlxt/bbs/bbs_tltb/${courseType}/viewTlById?wlkcid=${courseID}&id=${discussionID}&tabbh=${tabId}&bqid=${boardID}`;
|
|
174
|
+
|
|
175
|
+
export const LEARN_QUESTION_LIST_ANSWERED = (courseID: string, courseType: CourseType) =>
|
|
176
|
+
`${LEARN_PREFIX}/b/wlxt/bbs/bbs_tltb/${courseType}/kcdyList?wlkcid=${courseID}&size=${MAX_SIZE}`;
|
|
177
|
+
|
|
178
|
+
export const LEARN_QUESTION_DETAIL = (courseID: string, questionID: string, courseType: CourseType) =>
|
|
179
|
+
courseType === CourseType.STUDENT
|
|
180
|
+
? `${LEARN_PREFIX}/f/wlxt/bbs/bbs_kcdy/student/viewDyById?wlkcid=${courseID}&id=${questionID}`
|
|
181
|
+
: `${LEARN_PREFIX}/f/wlxt/bbs/bbs_kcdy/teacher/beforeEditDy?wlkcid=${courseID}&id=${questionID}`;
|
|
182
|
+
|
|
183
|
+
export const LEARN_QNR_LIST_ONGOING = `${LEARN_PREFIX}/b/wlxt/kcwj/wlkc_wjb/student/pageListWks`;
|
|
184
|
+
export const LEARN_QNR_LIST_ENDED = `${LEARN_PREFIX}/b/wlxt/kcwj/wlkc_wjb/student/pageListYjs`;
|
|
185
|
+
/** Note: This page is accessible even with an invalid `qnrID` as long as you have access to the given `courseID`. */
|
|
186
|
+
export const LEARN_QNR_SUBMIT_PAGE = (courseID: string, qnrID: string, type: QuestionnaireType) =>
|
|
187
|
+
`${LEARN_PREFIX}/f/wlxt/kcwj/wlkc_wjb/student/beforeAdd?wlkcid=${courseID}&wjid=${qnrID}&wjlx=${type}&jswj=no`;
|
|
188
|
+
export const LEARN_QNR_DETAIL = `${LEARN_PREFIX}/b/wlxt/kcwj/wlkc_wjb/student/getWjnr`;
|
|
189
|
+
|
|
190
|
+
export const LEARN_QNR_DETAIL_FORM = (courseID: string, qnrID: string) => {
|
|
191
|
+
const form = new FormData();
|
|
192
|
+
form.append('wlkcid', courseID);
|
|
193
|
+
form.append('wjid', qnrID);
|
|
194
|
+
return form;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
export const WebsiteShowLanguage = {
|
|
198
|
+
[Language.ZH]: 'zh_CN',
|
|
199
|
+
[Language.EN]: 'en_US',
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
export const LEARN_WEBSITE_LANGUAGE = (lang: Language) =>
|
|
203
|
+
`${LEARN_PREFIX}/f/wlxt/common/language?websiteShowLanguage=${WebsiteShowLanguage[lang]}`;
|
|
204
|
+
|
|
205
|
+
export const LEARN_FAVORITE_ADD = (type: ContentType, id: string) =>
|
|
206
|
+
`${LEARN_PREFIX}/b/xt/wlkc_xsscb/student/add?ywid=${id}&ywlx=${CONTENT_TYPE_MAP.get(type)}`;
|
|
207
|
+
|
|
208
|
+
export const LEARN_FAVORITE_REMOVE = (id: string) => `${LEARN_PREFIX}/b/xt/wlkc_xsscb/student/delete?ywid=${id}`;
|
|
209
|
+
|
|
210
|
+
export const LEARN_FAVORITE_LIST = (type?: ContentType) =>
|
|
211
|
+
`${LEARN_PREFIX}/b/xt/wlkc_xsscb/student/pageList?ywlx=${type ? CONTENT_TYPE_MAP.get(type) : 'ALL'}`;
|
|
212
|
+
|
|
213
|
+
export const LEARN_FAVORITE_PIN = `${LEARN_PREFIX}/b/xt/wlkc_xsscb/student/addZd`;
|
|
214
|
+
|
|
215
|
+
export const LEARN_FAVORITE_UNPIN = `${LEARN_PREFIX}/b/xt/wlkc_xsscb/student/delZd`;
|
|
216
|
+
|
|
217
|
+
export const LEARN_FAVORITE_PIN_UNPIN_FORM_DATA = (id: string) => {
|
|
218
|
+
const form = new FormData();
|
|
219
|
+
form.append('ywid', id);
|
|
220
|
+
return form;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
export const LEARN_COMMENT_SET = `${LEARN_PREFIX}/b/wlxt/xt/wlkc_xsbjb/add`;
|
|
224
|
+
|
|
225
|
+
export const LEARN_COMMENT_SET_FORM_DATA = (type: ContentType, id: string, content: string) => {
|
|
226
|
+
const form = new FormData();
|
|
227
|
+
form.append('ywlx', CONTENT_TYPE_MAP.get(type) ?? '');
|
|
228
|
+
form.append('ywid', id);
|
|
229
|
+
form.append('bznr', content);
|
|
230
|
+
return form;
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
export const LEARN_COMMENT_LIST = (type?: ContentType) =>
|
|
234
|
+
`${LEARN_PREFIX}/b/wlxt/xt/wlkc_xsbjb/student/pageList?ywlx=${type ? CONTENT_TYPE_MAP.get(type) : 'ALL'}`;
|
|
235
|
+
|
|
236
|
+
export const LEARN_PAGE_LIST_FORM_DATA = (courseID?: string) => {
|
|
237
|
+
const form = new FormData();
|
|
238
|
+
form.append('aoData', JSON.stringify(courseID ? [{ name: 'wlkcid', value: courseID }] : []));
|
|
239
|
+
return form;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
export const LEARN_SORT_COURSES = `${LEARN_PREFIX}/b/wlxt/kc/wlkc_kcpxb/addorUpdate`;
|
|
243
|
+
|
|
244
|
+
export const REGISTRAR_TICKET_FORM_DATA = () => {
|
|
245
|
+
const form = new FormData();
|
|
246
|
+
form.append('appId', 'ALL_ZHJW');
|
|
247
|
+
return form;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
export const REGISTRAR_TICKET = () => `${LEARN_PREFIX}/b/wlxt/common/auth/gnt`;
|
|
251
|
+
|
|
252
|
+
export const REGISTRAR_AUTH = (ticket: string) => `${REGISTRAR_PREFIX}/j_acegi_login.do?url=/&ticket=${ticket}`;
|
|
253
|
+
|
|
254
|
+
export const REGISTRAR_CALENDAR = (startDate: string, endDate: string, graduate = false, callbackName = 'unknown') =>
|
|
255
|
+
`${REGISTRAR_PREFIX}/jxmh_out.do?m=${
|
|
256
|
+
graduate ? 'yjs' : 'bks'
|
|
257
|
+
}_jxrl_all&p_start_date=${startDate}&p_end_date=${endDate}&jsoncallback=${callbackName}`;
|
package/src/user.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// User info and website language.
|
|
2
|
+
|
|
3
|
+
import type { Session } from './request.ts';
|
|
4
|
+
import { $ } from './request.ts';
|
|
5
|
+
import type { UserInfo, Language } from './types.ts';
|
|
6
|
+
import { CourseType } from './types.ts';
|
|
7
|
+
import * as URLS from './urls.ts';
|
|
8
|
+
|
|
9
|
+
/** get user's name and department */
|
|
10
|
+
export async function getUserInfo(s: Session, courseType = CourseType.STUDENT): Promise<UserInfo> {
|
|
11
|
+
const content = await (await s.fetchWithToken(URLS.LEARN_HOMEPAGE(courseType))).text();
|
|
12
|
+
|
|
13
|
+
const dom = $(content);
|
|
14
|
+
const name = dom('a.user-log').text().trim();
|
|
15
|
+
const department = dom('.fl.up-img-info p:nth-child(2) label').text().trim();
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
name,
|
|
19
|
+
department,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function setLanguage(s: Session, lang: Language): Promise<void> {
|
|
24
|
+
await s.fetchWithToken(URLS.LEARN_WEBSITE_LANGUAGE(lang), {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
});
|
|
27
|
+
s.lang = lang;
|
|
28
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { decodeHTML as _decodeHTML } from 'entities';
|
|
2
|
+
|
|
3
|
+
import type { DetailSelector } from './types.ts';
|
|
4
|
+
import { ContentType, FailReason, HomeworkGradeLevel, QuestionnaireType, SemesterType } from './types.ts';
|
|
5
|
+
|
|
6
|
+
export function parseSemesterType(n: number): SemesterType {
|
|
7
|
+
if (n === 1) {
|
|
8
|
+
return SemesterType.FALL;
|
|
9
|
+
} else if (n === 2) {
|
|
10
|
+
return SemesterType.SPRING;
|
|
11
|
+
} else if (n === 3) {
|
|
12
|
+
return SemesterType.SUMMER;
|
|
13
|
+
} else {
|
|
14
|
+
return SemesterType.UNKNOWN;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const CONTENT_TYPE_MK_MAP = {
|
|
19
|
+
[ContentType.NOTIFICATION]: 'kcgg',
|
|
20
|
+
[ContentType.FILE]: 'kcwj',
|
|
21
|
+
[ContentType.HOMEWORK]: 'kczy',
|
|
22
|
+
[ContentType.DISCUSSION]: '',
|
|
23
|
+
[ContentType.QUESTION]: '',
|
|
24
|
+
[ContentType.QUESTIONNAIRE]: '',
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function getMkFromType(type: ContentType): string {
|
|
28
|
+
return 'mk_' + (CONTENT_TYPE_MK_MAP[type] ?? 'UNKNOWN');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function decodeHTML(html: string): string {
|
|
32
|
+
const text = _decodeHTML(html ?? '');
|
|
33
|
+
// remove strange prefixes returned by web learning
|
|
34
|
+
return text.startsWith('\xC2\x9E\xC3\xA9\x65')
|
|
35
|
+
? text.slice(5)
|
|
36
|
+
: text.startsWith('\x9E\xE9\x65')
|
|
37
|
+
? text.slice(3)
|
|
38
|
+
: text.startsWith('\xE9\x65')
|
|
39
|
+
? text.slice(2)
|
|
40
|
+
: text;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function trimAndDefine(text: string | undefined | null): string | undefined {
|
|
44
|
+
if (text === undefined || text === null) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const trimmed = text.trim();
|
|
48
|
+
return trimmed === '' ? undefined : decodeHTML(trimmed);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const GRADE_LEVEL_MAP = new Map([
|
|
52
|
+
[-100, HomeworkGradeLevel.CHECKED],
|
|
53
|
+
[-99, HomeworkGradeLevel.A_PLUS],
|
|
54
|
+
[-98, HomeworkGradeLevel.A],
|
|
55
|
+
[-92, HomeworkGradeLevel.A_MINUS],
|
|
56
|
+
[-87, HomeworkGradeLevel.B_PLUS],
|
|
57
|
+
[-85, HomeworkGradeLevel.DISTINCTION],
|
|
58
|
+
[-82, HomeworkGradeLevel.B],
|
|
59
|
+
[-78, HomeworkGradeLevel.B_MINUS],
|
|
60
|
+
[-74, HomeworkGradeLevel.C_PLUS],
|
|
61
|
+
[-71, HomeworkGradeLevel.C],
|
|
62
|
+
[-68, HomeworkGradeLevel.C_MINUS],
|
|
63
|
+
[-67, HomeworkGradeLevel.G],
|
|
64
|
+
[-66, HomeworkGradeLevel.D_PLUS],
|
|
65
|
+
[-64, HomeworkGradeLevel.D],
|
|
66
|
+
[-65, HomeworkGradeLevel.EXEMPTED_COURSE],
|
|
67
|
+
[-63, HomeworkGradeLevel.PASS],
|
|
68
|
+
[-62, HomeworkGradeLevel.EX],
|
|
69
|
+
[-61, HomeworkGradeLevel.EXEMPTION],
|
|
70
|
+
[-60, HomeworkGradeLevel.PASS],
|
|
71
|
+
[-59, HomeworkGradeLevel.FAILURE],
|
|
72
|
+
[-55, HomeworkGradeLevel.W],
|
|
73
|
+
[-51, HomeworkGradeLevel.I],
|
|
74
|
+
[-50, HomeworkGradeLevel.INCOMPLETE],
|
|
75
|
+
[-31, HomeworkGradeLevel.NA],
|
|
76
|
+
[-30, HomeworkGradeLevel.F],
|
|
77
|
+
]);
|
|
78
|
+
|
|
79
|
+
export const JSONP_EXTRACTOR_NAME = 'thu_learn_lib_jsonp_extractor';
|
|
80
|
+
|
|
81
|
+
export function extractJSONPResult(jsonp: string): any {
|
|
82
|
+
// check jsonp format
|
|
83
|
+
if (!jsonp.startsWith(JSONP_EXTRACTOR_NAME)) {
|
|
84
|
+
throw FailReason.INVALID_RESPONSE;
|
|
85
|
+
}
|
|
86
|
+
// evaluate the result
|
|
87
|
+
// oxlint-disable-next-line typescript/no-implied-eval -- JSONP from the registrar is a JS expression, not JSON
|
|
88
|
+
return Function(`"use strict";const ${JSONP_EXTRACTOR_NAME}=(s)=>s;return ${jsonp};`)();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function formatFileSize(size: number): string {
|
|
92
|
+
// this logic is extracted from `judgeSize` function from Web Learning
|
|
93
|
+
if (size < 1024) return size + 'B';
|
|
94
|
+
if (size < 1024 * 1024) return (size / 1024).toFixed(2) + 'K';
|
|
95
|
+
if (size < 1024 * 1024 * 1024) return (size / 1024 / 1024).toFixed(2) + 'M';
|
|
96
|
+
return (size / 1024 / 1024 / 1024).toFixed(2) + 'G';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export const CONTENT_TYPE_MAP = new Map([
|
|
100
|
+
[ContentType.NOTIFICATION, 'KCGG'],
|
|
101
|
+
[ContentType.FILE, 'KCKJ'],
|
|
102
|
+
[ContentType.HOMEWORK, 'KCZY'],
|
|
103
|
+
[ContentType.DISCUSSION, 'KCTL'],
|
|
104
|
+
[ContentType.QUESTION, 'KCDY'],
|
|
105
|
+
[ContentType.QUESTIONNAIRE, 'KCWJ'],
|
|
106
|
+
// omitted: 课表(KCKB)
|
|
107
|
+
]);
|
|
108
|
+
export const CONTENT_TYPE_MAP_REVERSE = new Map([
|
|
109
|
+
[CONTENT_TYPE_MAP.get(ContentType.NOTIFICATION)!, ContentType.NOTIFICATION],
|
|
110
|
+
[CONTENT_TYPE_MAP.get(ContentType.FILE)!, ContentType.FILE],
|
|
111
|
+
[CONTENT_TYPE_MAP.get(ContentType.HOMEWORK)!, ContentType.HOMEWORK],
|
|
112
|
+
[CONTENT_TYPE_MAP.get(ContentType.DISCUSSION)!, ContentType.DISCUSSION],
|
|
113
|
+
[CONTENT_TYPE_MAP.get(ContentType.QUESTION)!, ContentType.QUESTION],
|
|
114
|
+
[CONTENT_TYPE_MAP.get(ContentType.QUESTIONNAIRE)!, ContentType.QUESTIONNAIRE],
|
|
115
|
+
]);
|
|
116
|
+
|
|
117
|
+
export const QNR_TYPE_MAP = new Map([
|
|
118
|
+
['投票', QuestionnaireType.VOTE],
|
|
119
|
+
['填表', QuestionnaireType.FORM],
|
|
120
|
+
['问卷', QuestionnaireType.SURVEY],
|
|
121
|
+
]);
|
|
122
|
+
|
|
123
|
+
/** whether `item` is selected by a `DetailSelector` (`undefined` means `'none'`) */
|
|
124
|
+
export const isSelected = <T>(selector: DetailSelector<T> | undefined, item: T): boolean =>
|
|
125
|
+
selector === 'all' || (typeof selector === 'function' && selector(item));
|