@robertying/thu-learn-lib 5.0.0 → 6.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/README.md +94 -227
- package/lib/auth.d.ts +15 -4
- package/lib/auth.d.ts.map +1 -1
- package/lib/auth.js +65 -55
- package/lib/auth.js.map +1 -1
- package/lib/calendar.d.ts +12 -5
- package/lib/calendar.d.ts.map +1 -1
- package/lib/calendar.js +118 -20
- package/lib/calendar.js.map +1 -1
- package/lib/contents.d.ts.map +1 -1
- package/lib/contents.js +10 -6
- package/lib/contents.js.map +1 -1
- package/lib/courses.d.ts.map +1 -1
- package/lib/courses.js +15 -29
- package/lib/courses.js.map +1 -1
- package/lib/discussions.d.ts.map +1 -1
- package/lib/discussions.js +8 -19
- package/lib/discussions.js.map +1 -1
- package/lib/favorites.d.ts +1 -0
- package/lib/favorites.d.ts.map +1 -1
- package/lib/favorites.js +25 -60
- package/lib/favorites.js.map +1 -1
- package/lib/files.d.ts +4 -4
- package/lib/files.d.ts.map +1 -1
- package/lib/files.js +112 -134
- package/lib/files.js.map +1 -1
- package/lib/homework.d.ts +35 -5
- package/lib/homework.d.ts.map +1 -1
- package/lib/homework.js +150 -92
- package/lib/homework.js.map +1 -1
- package/lib/index.d.ts +45 -20
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +52 -17
- package/lib/index.js.map +1 -1
- package/lib/notices.d.ts +4 -4
- package/lib/notices.d.ts.map +1 -1
- package/lib/notices.js +13 -33
- package/lib/notices.js.map +1 -1
- package/lib/questionnaires.d.ts +6 -3
- package/lib/questionnaires.d.ts.map +1 -1
- package/lib/questionnaires.js +26 -24
- package/lib/questionnaires.js.map +1 -1
- package/lib/request.d.ts +64 -20
- package/lib/request.d.ts.map +1 -1
- package/lib/request.js +174 -64
- package/lib/request.js.map +1 -1
- package/lib/timetable.d.ts +26 -0
- package/lib/timetable.d.ts.map +1 -0
- package/lib/timetable.js +110 -0
- package/lib/timetable.js.map +1 -0
- package/lib/types.d.ts +117 -76
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +3 -0
- package/lib/types.js.map +1 -1
- package/lib/urls.d.ts +10 -20
- package/lib/urls.d.ts.map +1 -1
- package/lib/urls.js +11 -56
- package/lib/urls.js.map +1 -1
- package/lib/user.d.ts +7 -2
- package/lib/user.d.ts.map +1 -1
- package/lib/user.js +20 -6
- package/lib/user.js.map +1 -1
- package/lib/utils.d.ts +42 -4
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +80 -29
- package/lib/utils.js.map +1 -1
- package/package.json +9 -8
- package/src/auth.ts +72 -70
- package/src/calendar.ts +136 -24
- package/src/contents.ts +13 -6
- package/src/courses.ts +21 -37
- package/src/discussions.ts +10 -21
- package/src/favorites.ts +44 -80
- package/src/files.ts +124 -142
- package/src/homework.ts +207 -135
- package/src/index.ts +79 -48
- package/src/notices.ts +29 -42
- package/src/questionnaires.ts +62 -45
- package/src/request.ts +192 -69
- package/src/timetable.ts +121 -0
- package/src/types.ts +123 -87
- package/src/urls.ts +13 -64
- package/src/user.ts +22 -7
- package/src/utils.ts +97 -29
package/lib/urls.js
CHANGED
|
@@ -1,25 +1,19 @@
|
|
|
1
|
-
import { FormData } from 'node-fetch-native';
|
|
2
1
|
import { CourseType, Language } from './types.js';
|
|
3
2
|
import { CONTENT_TYPE_MAP, getMkFromType } from './utils.js';
|
|
3
|
+
// URLs without parameters are constants; URLs with parameters, and form bodies (a new `FormData` each time), are
|
|
4
|
+
// functions. Form bodies use the global `FormData`, which Node (22+) and React Native both have.
|
|
4
5
|
export const ID_PREFIX = 'https://id.tsinghua.edu.cn';
|
|
5
6
|
export const LEARN_PREFIX = 'https://learn.tsinghua.edu.cn';
|
|
6
7
|
export const REGISTRAR_PREFIX = 'https://zhjw.cic.tsinghua.edu.cn';
|
|
7
8
|
const MAX_SIZE = 200;
|
|
8
|
-
export const ID_LOGIN =
|
|
9
|
-
export const ID_LOGIN_CHECK =
|
|
9
|
+
export const ID_LOGIN = `${ID_PREFIX}/do/off/ui/auth/login/form/bb5df85216504820be7bba2b0ae1535b/0`;
|
|
10
|
+
export const ID_LOGIN_CHECK = `${ID_PREFIX}/do/off/ui/auth/login/check`;
|
|
10
11
|
export const LEARN_AUTH_ROAM = (ticket) => `${LEARN_PREFIX}/b/j_spring_security_thauth_roaming_entry?ticket=${ticket}`;
|
|
11
|
-
export const LEARN_LOGOUT =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
else {
|
|
17
|
-
return `${LEARN_PREFIX}/f/wlxt/index/course/teacher/`;
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
export const LEARN_STUDENT_COURSE_LIST_PAGE = () => `${LEARN_PREFIX}/f/wlxt/index/course/student/`;
|
|
21
|
-
export const LEARN_SEMESTER_LIST = () => `${LEARN_PREFIX}/b/wlxt/kc/v_wlkc_xs_xktjb_coassb/queryxnxq`;
|
|
22
|
-
export const LEARN_CURRENT_SEMESTER = () => `${LEARN_PREFIX}/b/kc/zhjw_v_code_xnxq/getCurrentAndNextSemester`;
|
|
12
|
+
export const LEARN_LOGOUT = `${LEARN_PREFIX}/f/j_spring_security_logout`;
|
|
13
|
+
/** the homepage (course list) of a student or a teacher; login reads the CSRF token from the student one */
|
|
14
|
+
export const LEARN_HOMEPAGE = (courseType) => `${LEARN_PREFIX}/f/wlxt/index/course/${courseType}/`;
|
|
15
|
+
export const LEARN_SEMESTER_LIST = `${LEARN_PREFIX}/b/wlxt/kc/v_wlkc_xs_xktjb_coassb/queryxnxq`;
|
|
16
|
+
export const LEARN_CURRENT_SEMESTER = `${LEARN_PREFIX}/b/kc/zhjw_v_code_xnxq/getCurrentAndNextSemester`;
|
|
23
17
|
export const LEARN_COURSE_LIST = (semester, courseType, lang) => courseType === CourseType.STUDENT
|
|
24
18
|
? `${LEARN_PREFIX}/b/wlxt/kc/v_wlkc_xs_xkb_kcb_extend/student/loadCourseBySemesterId/${semester}/${lang}`
|
|
25
19
|
: `${LEARN_PREFIX}/b/kc/v_wlkc_kcb/queryAsorCoCourseList/${semester}/0`;
|
|
@@ -47,34 +41,10 @@ export const LEARN_NOTIFICATION_LIST = (courseType, expired) => `${LEARN_PREFIX}
|
|
|
47
41
|
export const LEARN_NOTIFICATION_DETAIL = (courseID, notificationID, courseType) => courseType === CourseType.STUDENT
|
|
48
42
|
? `${LEARN_PREFIX}/f/wlxt/kcgg/wlkc_ggb/student/beforeViewXs?wlkcid=${courseID}&id=${notificationID}`
|
|
49
43
|
: `${LEARN_PREFIX}/f/wlxt/kcgg/wlkc_ggb/teacher/beforeViewJs?wlkcid=${courseID}&id=${notificationID}`;
|
|
50
|
-
export const LEARN_NOTIFICATION_EDIT = (courseType) => `${LEARN_PREFIX}/b/wlxt/kcgg/wlkc_ggb/${courseType}/editKcgg`;
|
|
51
44
|
export const LEARN_HOMEWORK_LIST_NEW = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/zyListWj`;
|
|
52
45
|
export const LEARN_HOMEWORK_LIST_SUBMITTED = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/zyListYjwg`;
|
|
53
46
|
export const LEARN_HOMEWORK_LIST_GRADED = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/zyListYpg`;
|
|
54
47
|
export const LEARN_HOMEWORK_LIST_EXCELLENT = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/yxzylist`;
|
|
55
|
-
export const LEARN_HOMEWORK_LIST_SOURCE = [
|
|
56
|
-
{
|
|
57
|
-
url: LEARN_HOMEWORK_LIST_NEW,
|
|
58
|
-
status: {
|
|
59
|
-
submitted: false,
|
|
60
|
-
graded: false,
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
url: LEARN_HOMEWORK_LIST_SUBMITTED,
|
|
65
|
-
status: {
|
|
66
|
-
submitted: true,
|
|
67
|
-
graded: false,
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
url: LEARN_HOMEWORK_LIST_GRADED,
|
|
72
|
-
status: {
|
|
73
|
-
submitted: true,
|
|
74
|
-
graded: true,
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
];
|
|
78
48
|
export const LEARN_HOMEWORK_PAGE = (courseID, id) => `${LEARN_PREFIX}/f/wlxt/kczy/zy/student/viewCj?wlkcid=${courseID}&xszyid=${id}`;
|
|
79
49
|
export const LEARN_HOMEWORK_EXCELLENT_PAGE = (courseID, id) => `${LEARN_PREFIX}/f/wlxt/kczy/zy/student/viewYxzy?wlkcid=${courseID}&xszyid=${id}`;
|
|
80
50
|
export const LEARN_HOMEWORK_DETAIL = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/detail`;
|
|
@@ -83,23 +53,8 @@ export const LEARN_HOMEWORK_DETAIL_FORM_DATA = (baseId) => {
|
|
|
83
53
|
form.append('id', baseId);
|
|
84
54
|
return form;
|
|
85
55
|
};
|
|
86
|
-
export const LEARN_HOMEWORK_DOWNLOAD = (courseID, attachmentID) => `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/downloadFile/${courseID}/${attachmentID}`;
|
|
87
56
|
export const LEARN_HOMEWORK_SUBMIT_PAGE = (courseID, id) => `${LEARN_PREFIX}/f/wlxt/kczy/zy/student/tijiao?wlkcid=${courseID}&xszyid=${id}`;
|
|
88
|
-
export const LEARN_HOMEWORK_SUBMIT =
|
|
89
|
-
export const LEARN_HOMEWORK_SUBMIT_FORM_DATA = (id, content = '', attachment, removeAttachment = false) => {
|
|
90
|
-
const form = new FormData();
|
|
91
|
-
form.append('xszyid', id);
|
|
92
|
-
form.append('zynr', content ?? '');
|
|
93
|
-
if (attachment)
|
|
94
|
-
form.append('fileupload', attachment.content, attachment.filename);
|
|
95
|
-
else
|
|
96
|
-
form.append('fileupload', 'undefined');
|
|
97
|
-
if (removeAttachment)
|
|
98
|
-
form.append('isDeleted', '1');
|
|
99
|
-
else
|
|
100
|
-
form.append('isDeleted', '0');
|
|
101
|
-
return form;
|
|
102
|
-
};
|
|
57
|
+
export const LEARN_HOMEWORK_SUBMIT = `${LEARN_PREFIX}/b/wlxt/kczy/zy/student/tjzy`;
|
|
103
58
|
export const LEARN_HOMEWORK_LIST_TEACHER = `${LEARN_PREFIX}/b/wlxt/kczy/zy/teacher/pageList`;
|
|
104
59
|
export const LEARN_HOMEWORK_DETAIL_TEACHER = (courseID, homeworkID) => `${LEARN_PREFIX}/f/wlxt/kczy/xszy/teacher/beforePageList?zyid=${homeworkID}&wlkcid=${courseID}`;
|
|
105
60
|
export const LEARN_DISCUSSION_LIST = (courseID, courseType) => `${LEARN_PREFIX}/b/wlxt/bbs/bbs_tltb/${courseType}/kctlList?wlkcid=${courseID}&size=${MAX_SIZE}`;
|
|
@@ -154,7 +109,7 @@ export const REGISTRAR_TICKET_FORM_DATA = () => {
|
|
|
154
109
|
form.append('appId', 'ALL_ZHJW');
|
|
155
110
|
return form;
|
|
156
111
|
};
|
|
157
|
-
export const REGISTRAR_TICKET =
|
|
112
|
+
export const REGISTRAR_TICKET = `${LEARN_PREFIX}/b/wlxt/common/auth/gnt`;
|
|
158
113
|
export const REGISTRAR_AUTH = (ticket) => `${REGISTRAR_PREFIX}/j_acegi_login.do?url=/&ticket=${ticket}`;
|
|
159
114
|
export const REGISTRAR_CALENDAR = (startDate, endDate, graduate = false, callbackName = 'unknown') => `${REGISTRAR_PREFIX}/jxmh_out.do?m=${graduate ? 'yjs' : 'bks'}_jxrl_all&p_start_date=${startDate}&p_end_date=${endDate}&jsoncallback=${callbackName}`;
|
|
160
115
|
//# sourceMappingURL=urls.js.map
|
package/lib/urls.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urls.js","sourceRoot":"","sources":["../src/urls.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"urls.js","sourceRoot":"","sources":["../src/urls.ts"],"names":[],"mappings":"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"}
|
package/lib/user.d.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import type { Session } from './request.ts';
|
|
2
|
-
import type {
|
|
2
|
+
import type { Language, UserInfo } from './types.ts';
|
|
3
3
|
import { CourseType } from './types.ts';
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* get user's name and department (`''` if the page shows none)
|
|
6
|
+
*
|
|
7
|
+
* The homepage's profile card (`.fl.up-img-info`) has two `<p>`: the name and role labels (同学 / Student), then the
|
|
8
|
+
* department label (for undergraduates, their 书院). The name is also in the header's `a.user-log`.
|
|
9
|
+
*/
|
|
5
10
|
export declare function getUserInfo(s: Session, courseType?: CourseType): Promise<UserInfo>;
|
|
6
11
|
export declare function setLanguage(s: Session, lang: Language): Promise<void>;
|
|
7
12
|
//# sourceMappingURL=user.d.ts.map
|
package/lib/user.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,UAAU,EAAc,MAAM,YAAY,CAAC;AAOpD;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,aAAqB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAYhG;AAED,wBAAsB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAU3E"}
|
package/lib/user.js
CHANGED
|
@@ -1,22 +1,36 @@
|
|
|
1
1
|
// User info and website language.
|
|
2
|
-
import {
|
|
3
|
-
import { CourseType } from './types.js';
|
|
2
|
+
import { discard } from './request.js';
|
|
3
|
+
import { CourseType, FailReason } from './types.js';
|
|
4
4
|
import * as URLS from './urls.js';
|
|
5
|
-
|
|
5
|
+
import { $, apiError } from './utils.js';
|
|
6
|
+
/** what the English homepage shows for a department without an English name (as for the 书院) */
|
|
7
|
+
const NO_DEPARTMENT = 'none';
|
|
8
|
+
/**
|
|
9
|
+
* get user's name and department (`''` if the page shows none)
|
|
10
|
+
*
|
|
11
|
+
* The homepage's profile card (`.fl.up-img-info`) has two `<p>`: the name and role labels (同学 / Student), then the
|
|
12
|
+
* department label (for undergraduates, their 书院). The name is also in the header's `a.user-log`.
|
|
13
|
+
*/
|
|
6
14
|
export async function getUserInfo(s, courseType = CourseType.STUDENT) {
|
|
7
|
-
const content = await
|
|
15
|
+
const content = await s.fetchTextWithToken(URLS.LEARN_HOMEPAGE(courseType));
|
|
8
16
|
const dom = $(content);
|
|
9
17
|
const name = dom('a.user-log').text().trim();
|
|
10
|
-
const
|
|
18
|
+
const label = dom('.fl.up-img-info p:nth-child(2) label').text().trim();
|
|
19
|
+
const department = label.toLowerCase() === NO_DEPARTMENT ? '' : label;
|
|
11
20
|
return {
|
|
12
21
|
name,
|
|
13
22
|
department,
|
|
14
23
|
};
|
|
15
24
|
}
|
|
16
25
|
export async function setLanguage(s, lang) {
|
|
17
|
-
await s.fetchWithToken(URLS.LEARN_WEBSITE_LANGUAGE(lang), {
|
|
26
|
+
const response = await s.fetchWithToken(URLS.LEARN_WEBSITE_LANGUAGE(lang), {
|
|
18
27
|
method: 'POST',
|
|
19
28
|
});
|
|
29
|
+
// free the connection; only the status matters
|
|
30
|
+
discard(response);
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw apiError(FailReason.OPERATION_FAILED, { code: response.status, text: response.statusText });
|
|
33
|
+
}
|
|
20
34
|
s.lang = lang;
|
|
21
35
|
}
|
|
22
36
|
//# sourceMappingURL=user.js.map
|
package/lib/user.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.js","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAGlC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"user.js","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAGlC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEzC,+FAA+F;AAC/F,MAAM,aAAa,GAAG,MAAM,CAAC;AAE7B;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,CAAU,EAAE,UAAU,GAAG,UAAU,CAAC,OAAO;IAC3E,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAE5E,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;IACvB,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;IAC7C,MAAM,KAAK,GAAG,GAAG,CAAC,sCAAsC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;IACxE,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,KAAK,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAEtE,OAAO;QACL,IAAI;QACJ,UAAU;KACX,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,CAAU,EAAE,IAAc;IAC1D,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,EAAE;QACzE,MAAM,EAAE,MAAM;KACf,CAAC,CAAC;IACH,+CAA+C;IAC/C,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,QAAQ,CAAC,UAAU,CAAC,gBAAgB,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IACpG,CAAC;IACD,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC;AAChB,CAAC"}
|
package/lib/utils.d.ts
CHANGED
|
@@ -1,12 +1,50 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import * as cheerio from 'cheerio';
|
|
2
|
+
import type { ApiError, DetailSelector, Fetch } from './types.ts';
|
|
3
|
+
import { ContentType, FailReason, HomeworkGradeLevel, QuestionnaireType, SemesterType } from './types.ts';
|
|
4
|
+
/**
|
|
5
|
+
* The error every API rejects with: a plain `{ reason, extra }` object (not an `Error`), so callers can compare
|
|
6
|
+
* `reason` with `FailReason`. `extra` is left out when not given.
|
|
7
|
+
*/
|
|
8
|
+
export declare const apiError: (reason: FailReason, extra?: unknown) => ApiError;
|
|
9
|
+
/** throw `apiError(reason, json)` unless the server's JSON answer says `result: 'success'` */
|
|
10
|
+
export declare function expectSuccess(json: any, reason: FailReason): void;
|
|
11
|
+
/** a DOM element as cheerio's selections hold it (domhandler's `Element`, taken from cheerio's types so it always matches) */
|
|
12
|
+
export type Element = ReturnType<ReturnType<cheerio.CheerioAPI['root']>['children']>[number];
|
|
13
|
+
/** load an HTML page or fragment for querying */
|
|
14
|
+
export declare const $: (html: Parameters<typeof cheerio.load>[0]) => cheerio.CheerioAPI;
|
|
15
|
+
/** what the server writes for "yes" in its flags (and 否 for "no") */
|
|
16
|
+
export declare const YES = "\u662F";
|
|
17
|
+
/** the URL of a `fetch` input */
|
|
18
|
+
export declare const urlOf: (input: Parameters<Fetch>[0]) => string;
|
|
19
|
+
/**
|
|
20
|
+
* Whether a 200 page is the short login or redirect page of an expired session rather than the page asked for: short,
|
|
21
|
+
* and either Web Learning's "login timeout" page (what the server sends for an HTML page of an expired session, in
|
|
22
|
+
* either website language: title 登录超时, image `log_fail.png`, text 您未登录或登录失效) or a page pointing at the
|
|
23
|
+
* login timeout page or the SSO login.
|
|
24
|
+
*/
|
|
25
|
+
export declare const looksLikeLoginPage: (text: string) => boolean;
|
|
26
|
+
/** the semester type from the last digit of a semester id (`2024-2025-1`) */
|
|
27
|
+
export declare const parseSemesterType: (n: number) => SemesterType;
|
|
4
28
|
export declare function getMkFromType(type: ContentType): string;
|
|
5
29
|
export declare function decodeHTML(html: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* A server time as an ISO 8601 string in Beijing time with its offset, e.g. `2026-11-07T18:28:00+08:00`. The server
|
|
32
|
+
* sends either a Unix timestamp (a number or a string of digits; milliseconds, or seconds for a 10-digit value such as
|
|
33
|
+
* a favorite's pin time) or a Beijing wall-clock time without a zone (`2026-11-07 18:28`, `2026-11-07 18:28:00`).
|
|
34
|
+
* `undefined` for a missing or empty value, or a timestamp that is 0, negative or out of range; a string in any other
|
|
35
|
+
* shape is returned as it is, so nothing the server sent is lost.
|
|
36
|
+
*/
|
|
37
|
+
export declare function toServerTime(value: unknown): string | undefined;
|
|
38
|
+
/** `toServerTime` for a time every item has; '' when the server left it out */
|
|
39
|
+
export declare const toRequiredServerTime: (value: unknown) => string;
|
|
6
40
|
export declare function trimAndDefine(text: string | undefined | null): string | undefined;
|
|
7
41
|
export declare const GRADE_LEVEL_MAP: Map<number, HomeworkGradeLevel>;
|
|
8
42
|
export declare const JSONP_EXTRACTOR_NAME = "thu_learn_lib_jsonp_extractor";
|
|
9
|
-
|
|
43
|
+
/**
|
|
44
|
+
* The argument of a `thu_learn_lib_jsonp_extractor(...)` JSONP body, parsed as JSON. The body is never run as code,
|
|
45
|
+
* so whatever the registrar (or anything between) sends can't execute in the app.
|
|
46
|
+
*/
|
|
47
|
+
export declare function extractJSONPResult(jsonp: string): unknown;
|
|
10
48
|
export declare function formatFileSize(size: number): string;
|
|
11
49
|
export declare const CONTENT_TYPE_MAP: Map<ContentType, string>;
|
|
12
50
|
export declare const CONTENT_TYPE_MAP_REVERSE: Map<string, ContentType>;
|
package/lib/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAGnC,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI1G;;;GAGG;AACH,eAAO,MAAM,QAAQ,WAAY,UAAU,UAAU,OAAO,KAAG,QACT,CAAC;AAEvD,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAEjE;AAED,8HAA8H;AAC9H,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7F,iDAAiD;AACjD,eAAO,MAAM,CAAC,SAAU,UAAU,CAAC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,UAAgD,CAAC;AAEtH,qEAAqE;AACrE,eAAO,MAAM,GAAG,WAAM,CAAC;AAEvB,iCAAiC;AACjC,eAAO,MAAM,KAAK,UAAW,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAG,MAC+B,CAAC;AAKpF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,SAAU,MAAM,YAI5C,CAAC;AAQJ,6EAA6E;AAC7E,eAAO,MAAM,iBAAiB,MAAO,MAAM,KAAG,YAAyD,CAAC;AAWxG,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAEvD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAU/C;AAID;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAc/D;AAED,+EAA+E;AAC/E,eAAO,MAAM,oBAAoB,UAAW,OAAO,KAAG,MAAmC,CAAC;AAE1F,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAMjF;AAED,eAAO,MAAM,eAAe,iCA0B1B,CAAC;AAEH,eAAO,MAAM,oBAAoB,kCAAkC,CAAC;AAEpE;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAWzD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMnD;AAED,eAAO,MAAM,gBAAgB,0BAQ3B,CAAC;AACH,eAAO,MAAM,wBAAwB,0BAAqE,CAAC;AAE3G,eAAO,MAAM,YAAY,gCAIvB,CAAC;AAEH,oFAAoF;AACpF,eAAO,MAAM,UAAU,GAAI,CAAC,YAAY,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,QAAQ,CAAC,KAAG,OACP,CAAC"}
|
package/lib/utils.js
CHANGED
|
@@ -1,19 +1,40 @@
|
|
|
1
|
+
import * as cheerio from 'cheerio';
|
|
1
2
|
import { decodeHTML as _decodeHTML } from 'entities';
|
|
2
3
|
import { ContentType, FailReason, HomeworkGradeLevel, QuestionnaireType, SemesterType } from './types.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
else {
|
|
14
|
-
return SemesterType.UNKNOWN;
|
|
15
|
-
}
|
|
4
|
+
const CHEERIO_CONFIG = { xml: true };
|
|
5
|
+
/**
|
|
6
|
+
* The error every API rejects with: a plain `{ reason, extra }` object (not an `Error`), so callers can compare
|
|
7
|
+
* `reason` with `FailReason`. `extra` is left out when not given.
|
|
8
|
+
*/
|
|
9
|
+
export const apiError = (reason, extra) => extra === undefined ? { reason } : { reason, extra };
|
|
10
|
+
/** throw `apiError(reason, json)` unless the server's JSON answer says `result: 'success'` */
|
|
11
|
+
export function expectSuccess(json, reason) {
|
|
12
|
+
if (json?.result !== 'success')
|
|
13
|
+
throw apiError(reason, json);
|
|
16
14
|
}
|
|
15
|
+
/** load an HTML page or fragment for querying */
|
|
16
|
+
export const $ = (html) => cheerio.load(html, CHEERIO_CONFIG);
|
|
17
|
+
/** what the server writes for "yes" in its flags (and 否 for "no") */
|
|
18
|
+
export const YES = '是';
|
|
19
|
+
/** the URL of a `fetch` input */
|
|
20
|
+
export const urlOf = (input) => typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
|
|
21
|
+
/** pages longer than this are taken as real pages, never as the short login / redirect page of an expired session */
|
|
22
|
+
const MAX_LOGIN_PAGE_LENGTH = 4096;
|
|
23
|
+
/**
|
|
24
|
+
* Whether a 200 page is the short login or redirect page of an expired session rather than the page asked for: short,
|
|
25
|
+
* and either Web Learning's "login timeout" page (what the server sends for an HTML page of an expired session, in
|
|
26
|
+
* either website language: title 登录超时, image `log_fail.png`, text 您未登录或登录失效) or a page pointing at the
|
|
27
|
+
* login timeout page or the SSO login.
|
|
28
|
+
*/
|
|
29
|
+
export const looksLikeLoginPage = (text) => text.length < MAX_LOGIN_PAGE_LENGTH &&
|
|
30
|
+
/登录超时|您未登录或登录失效|log_fail\.png|login_timeout|id\.tsinghua\.edu\.cn\/do\/off\/ui\/auth\/login|j_spring_security_thauth_roaming_entry/.test(text);
|
|
31
|
+
const SEMESTER_TYPES = {
|
|
32
|
+
1: SemesterType.FALL,
|
|
33
|
+
2: SemesterType.SPRING,
|
|
34
|
+
3: SemesterType.SUMMER,
|
|
35
|
+
};
|
|
36
|
+
/** the semester type from the last digit of a semester id (`2024-2025-1`) */
|
|
37
|
+
export const parseSemesterType = (n) => SEMESTER_TYPES[n] ?? SemesterType.UNKNOWN;
|
|
17
38
|
const CONTENT_TYPE_MK_MAP = {
|
|
18
39
|
[ContentType.NOTIFICATION]: 'kcgg',
|
|
19
40
|
[ContentType.FILE]: 'kcwj',
|
|
@@ -23,7 +44,7 @@ const CONTENT_TYPE_MK_MAP = {
|
|
|
23
44
|
[ContentType.QUESTIONNAIRE]: '',
|
|
24
45
|
};
|
|
25
46
|
export function getMkFromType(type) {
|
|
26
|
-
return 'mk_' +
|
|
47
|
+
return 'mk_' + CONTENT_TYPE_MK_MAP[type];
|
|
27
48
|
}
|
|
28
49
|
export function decodeHTML(html) {
|
|
29
50
|
const text = _decodeHTML(html ?? '');
|
|
@@ -36,6 +57,35 @@ export function decodeHTML(html) {
|
|
|
36
57
|
? text.slice(2)
|
|
37
58
|
: text;
|
|
38
59
|
}
|
|
60
|
+
const BEIJING_OFFSET_MS = 8 * 60 * 60 * 1000;
|
|
61
|
+
/**
|
|
62
|
+
* A server time as an ISO 8601 string in Beijing time with its offset, e.g. `2026-11-07T18:28:00+08:00`. The server
|
|
63
|
+
* sends either a Unix timestamp (a number or a string of digits; milliseconds, or seconds for a 10-digit value such as
|
|
64
|
+
* a favorite's pin time) or a Beijing wall-clock time without a zone (`2026-11-07 18:28`, `2026-11-07 18:28:00`).
|
|
65
|
+
* `undefined` for a missing or empty value, or a timestamp that is 0, negative or out of range; a string in any other
|
|
66
|
+
* shape is returned as it is, so nothing the server sent is lost.
|
|
67
|
+
*/
|
|
68
|
+
export function toServerTime(value) {
|
|
69
|
+
if (value === null || value === undefined || value === '')
|
|
70
|
+
return undefined;
|
|
71
|
+
if (typeof value === 'number' || (typeof value === 'string' && /^\d{10,}$/.test(value))) {
|
|
72
|
+
const number = Number(value);
|
|
73
|
+
// 0 (or less) is the server's "no time", e.g. a homework without a late submission deadline
|
|
74
|
+
if (!Number.isFinite(number) || number <= 0)
|
|
75
|
+
return undefined;
|
|
76
|
+
// seconds until the year 5138, milliseconds after 1973
|
|
77
|
+
const date = new Date((number < 1e11 ? number * 1000 : number) + BEIJING_OFFSET_MS);
|
|
78
|
+
if (Number.isNaN(date.getTime()))
|
|
79
|
+
return undefined;
|
|
80
|
+
return date.toISOString().replace(/(\.\d{3})?Z$/, '+08:00');
|
|
81
|
+
}
|
|
82
|
+
if (typeof value !== 'string')
|
|
83
|
+
return undefined;
|
|
84
|
+
const wallClock = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2})(:\d{2})?(?:\.\d+)?$/.exec(value.trim());
|
|
85
|
+
return wallClock ? `${wallClock[1]}T${wallClock[2]}${wallClock[3] ?? ':00'}+08:00` : value;
|
|
86
|
+
}
|
|
87
|
+
/** `toServerTime` for a time every item has; '' when the server left it out */
|
|
88
|
+
export const toRequiredServerTime = (value) => toServerTime(value) ?? '';
|
|
39
89
|
export function trimAndDefine(text) {
|
|
40
90
|
if (text === undefined || text === null) {
|
|
41
91
|
return undefined;
|
|
@@ -59,7 +109,7 @@ export const GRADE_LEVEL_MAP = new Map([
|
|
|
59
109
|
[-66, HomeworkGradeLevel.D_PLUS],
|
|
60
110
|
[-64, HomeworkGradeLevel.D],
|
|
61
111
|
[-65, HomeworkGradeLevel.EXEMPTED_COURSE],
|
|
62
|
-
[-63, HomeworkGradeLevel.
|
|
112
|
+
[-63, HomeworkGradeLevel.P],
|
|
63
113
|
[-62, HomeworkGradeLevel.EX],
|
|
64
114
|
[-61, HomeworkGradeLevel.EXEMPTION],
|
|
65
115
|
[-60, HomeworkGradeLevel.PASS],
|
|
@@ -71,14 +121,22 @@ export const GRADE_LEVEL_MAP = new Map([
|
|
|
71
121
|
[-30, HomeworkGradeLevel.F],
|
|
72
122
|
]);
|
|
73
123
|
export const JSONP_EXTRACTOR_NAME = 'thu_learn_lib_jsonp_extractor';
|
|
124
|
+
/**
|
|
125
|
+
* The argument of a `thu_learn_lib_jsonp_extractor(...)` JSONP body, parsed as JSON. The body is never run as code,
|
|
126
|
+
* so whatever the registrar (or anything between) sends can't execute in the app.
|
|
127
|
+
*/
|
|
74
128
|
export function extractJSONPResult(jsonp) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
129
|
+
const prefix = `${JSONP_EXTRACTOR_NAME}(`;
|
|
130
|
+
const body = jsonp.trim().replace(/;$/, '').trimEnd();
|
|
131
|
+
if (!body.startsWith(prefix) || !body.endsWith(')')) {
|
|
132
|
+
throw apiError(FailReason.INVALID_RESPONSE, jsonp.slice(0, 200));
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
return JSON.parse(body.slice(prefix.length, -1));
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
throw apiError(FailReason.INVALID_RESPONSE, { error: String(err), text: jsonp.slice(0, 200) });
|
|
78
139
|
}
|
|
79
|
-
// evaluate the result
|
|
80
|
-
// oxlint-disable-next-line typescript/no-implied-eval -- JSONP from the registrar is a JS expression, not JSON
|
|
81
|
-
return Function(`"use strict";const ${JSONP_EXTRACTOR_NAME}=(s)=>s;return ${jsonp};`)();
|
|
82
140
|
}
|
|
83
141
|
export function formatFileSize(size) {
|
|
84
142
|
// this logic is extracted from `judgeSize` function from Web Learning
|
|
@@ -99,14 +157,7 @@ export const CONTENT_TYPE_MAP = new Map([
|
|
|
99
157
|
[ContentType.QUESTIONNAIRE, 'KCWJ'],
|
|
100
158
|
// omitted: 课表(KCKB)
|
|
101
159
|
]);
|
|
102
|
-
export const CONTENT_TYPE_MAP_REVERSE = new Map([
|
|
103
|
-
[CONTENT_TYPE_MAP.get(ContentType.NOTIFICATION), ContentType.NOTIFICATION],
|
|
104
|
-
[CONTENT_TYPE_MAP.get(ContentType.FILE), ContentType.FILE],
|
|
105
|
-
[CONTENT_TYPE_MAP.get(ContentType.HOMEWORK), ContentType.HOMEWORK],
|
|
106
|
-
[CONTENT_TYPE_MAP.get(ContentType.DISCUSSION), ContentType.DISCUSSION],
|
|
107
|
-
[CONTENT_TYPE_MAP.get(ContentType.QUESTION), ContentType.QUESTION],
|
|
108
|
-
[CONTENT_TYPE_MAP.get(ContentType.QUESTIONNAIRE), ContentType.QUESTIONNAIRE],
|
|
109
|
-
]);
|
|
160
|
+
export const CONTENT_TYPE_MAP_REVERSE = new Map([...CONTENT_TYPE_MAP].map(([type, code]) => [code, type]));
|
|
110
161
|
export const QNR_TYPE_MAP = new Map([
|
|
111
162
|
['投票', QuestionnaireType.VOTE],
|
|
112
163
|
['填表', QuestionnaireType.FORM],
|
package/lib/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,WAAW,EAAE,MAAM,UAAU,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1G,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@robertying/thu-learn-lib",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "a JavaScript library to provide a program-friendly interface to Web Learning (2018) of Tsinghua University",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"learn2018",
|
|
@@ -39,23 +39,24 @@
|
|
|
39
39
|
"lint": "oxlint",
|
|
40
40
|
"format": "oxfmt",
|
|
41
41
|
"test": "vitest run",
|
|
42
|
+
"test:coverage": "vitest run --coverage",
|
|
42
43
|
"test:live": "OPENSSL_CONF=openssl.cnf vitest run --config vitest.live.config.ts",
|
|
43
44
|
"prepublishOnly": "pnpm build"
|
|
44
45
|
},
|
|
45
46
|
"dependencies": {
|
|
46
|
-
"cheerio": "1.
|
|
47
|
-
"entities": "^
|
|
48
|
-
"fetch-cookie": "3.0
|
|
47
|
+
"cheerio": "1.2.0",
|
|
48
|
+
"entities": "^9.0.0",
|
|
49
|
+
"fetch-cookie": "3.2.0",
|
|
49
50
|
"js-base64": "^3.9.3",
|
|
50
51
|
"node-fetch-native": "^1.6.7",
|
|
51
52
|
"sm-crypto": "^0.5.7",
|
|
52
|
-
"tough-cookie": "
|
|
53
|
+
"tough-cookie": "6.1.0"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
56
|
"@types/node": "26.6.6",
|
|
56
57
|
"@types/sm-crypto": "0.3.4",
|
|
57
|
-
"@
|
|
58
|
-
"dotenv": "
|
|
58
|
+
"@vitest/coverage-v8": "5.1.0",
|
|
59
|
+
"dotenv": "18.0.9",
|
|
59
60
|
"oxfmt": "0.77.0",
|
|
60
61
|
"oxlint": "1.92.0",
|
|
61
62
|
"oxlint-tsgolint": "7.0.2006",
|
|
@@ -63,7 +64,7 @@
|
|
|
63
64
|
"vitest": "5.1.0"
|
|
64
65
|
},
|
|
65
66
|
"engines": {
|
|
66
|
-
"node": ">=
|
|
67
|
+
"node": ">=22"
|
|
67
68
|
},
|
|
68
69
|
"packageManager": "pnpm@12.18.0"
|
|
69
70
|
}
|