@robertying/thu-learn-lib 0.0.0-stage → 4.1.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 +52 -0
- package/lib/contents.js.map +1 -0
- package/lib/courses.d.ts +9 -0
- package/lib/courses.d.ts.map +1 -0
- package/lib/courses.js +82 -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 +9 -0
- package/lib/homework.d.ts.map +1 -0
- package/lib/homework.js +193 -0
- package/lib/homework.js.map +1 -0
- package/lib/index.d.ts +105 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +181 -0
- package/lib/index.js.map +1 -0
- package/lib/notices.d.ts +6 -0
- package/lib/notices.d.ts.map +1 -0
- package/lib/notices.js +84 -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 +31 -0
- package/lib/request.d.ts.map +1 -0
- package/lib/request.js +90 -0
- package/lib/request.js.map +1 -0
- package/lib/types.d.ts +392 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +97 -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 +13 -0
- package/lib/utils.d.ts.map +1 -0
- package/lib/utils.js +115 -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 +67 -0
- package/src/courses.ts +97 -0
- package/src/discussions.ts +80 -0
- package/src/favorites.ts +167 -0
- package/src/files.ts +197 -0
- package/src/homework.ts +279 -0
- package/src/index.ts +282 -0
- package/src/notices.ts +110 -0
- package/src/questionnaires.ts +76 -0
- package/src/request.ts +101 -0
- package/src/types.ts +445 -0
- package/src/urls.ts +257 -0
- package/src/user.ts +28 -0
- package/src/utils.ts +120 -0
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,120 @@
|
|
|
1
|
+
import { decodeHTML as _decodeHTML } from 'entities';
|
|
2
|
+
|
|
3
|
+
import { ContentType, FailReason, HomeworkGradeLevel, QuestionnaireType, SemesterType } from './types.ts';
|
|
4
|
+
|
|
5
|
+
export function parseSemesterType(n: number): SemesterType {
|
|
6
|
+
if (n === 1) {
|
|
7
|
+
return SemesterType.FALL;
|
|
8
|
+
} else if (n === 2) {
|
|
9
|
+
return SemesterType.SPRING;
|
|
10
|
+
} else if (n === 3) {
|
|
11
|
+
return SemesterType.SUMMER;
|
|
12
|
+
} else {
|
|
13
|
+
return SemesterType.UNKNOWN;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const CONTENT_TYPE_MK_MAP = {
|
|
18
|
+
[ContentType.NOTIFICATION]: 'kcgg',
|
|
19
|
+
[ContentType.FILE]: 'kcwj',
|
|
20
|
+
[ContentType.HOMEWORK]: 'kczy',
|
|
21
|
+
[ContentType.DISCUSSION]: '',
|
|
22
|
+
[ContentType.QUESTION]: '',
|
|
23
|
+
[ContentType.QUESTIONNAIRE]: '',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export function getMkFromType(type: ContentType): string {
|
|
27
|
+
return 'mk_' + (CONTENT_TYPE_MK_MAP[type] ?? 'UNKNOWN');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function decodeHTML(html: string): string {
|
|
31
|
+
const text = _decodeHTML(html ?? '');
|
|
32
|
+
// remove strange prefixes returned by web learning
|
|
33
|
+
return text.startsWith('\xC2\x9E\xC3\xA9\x65')
|
|
34
|
+
? text.slice(5)
|
|
35
|
+
: text.startsWith('\x9E\xE9\x65')
|
|
36
|
+
? text.slice(3)
|
|
37
|
+
: text.startsWith('\xE9\x65')
|
|
38
|
+
? text.slice(2)
|
|
39
|
+
: text;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function trimAndDefine(text: string | undefined | null): string | undefined {
|
|
43
|
+
if (text === undefined || text === null) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const trimmed = text.trim();
|
|
47
|
+
return trimmed === '' ? undefined : decodeHTML(trimmed);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const GRADE_LEVEL_MAP = new Map([
|
|
51
|
+
[-100, HomeworkGradeLevel.CHECKED],
|
|
52
|
+
[-99, HomeworkGradeLevel.A_PLUS],
|
|
53
|
+
[-98, HomeworkGradeLevel.A],
|
|
54
|
+
[-92, HomeworkGradeLevel.A_MINUS],
|
|
55
|
+
[-87, HomeworkGradeLevel.B_PLUS],
|
|
56
|
+
[-85, HomeworkGradeLevel.DISTINCTION],
|
|
57
|
+
[-82, HomeworkGradeLevel.B],
|
|
58
|
+
[-78, HomeworkGradeLevel.B_MINUS],
|
|
59
|
+
[-74, HomeworkGradeLevel.C_PLUS],
|
|
60
|
+
[-71, HomeworkGradeLevel.C],
|
|
61
|
+
[-68, HomeworkGradeLevel.C_MINUS],
|
|
62
|
+
[-67, HomeworkGradeLevel.G],
|
|
63
|
+
[-66, HomeworkGradeLevel.D_PLUS],
|
|
64
|
+
[-64, HomeworkGradeLevel.D],
|
|
65
|
+
[-65, HomeworkGradeLevel.EXEMPTED_COURSE],
|
|
66
|
+
[-63, HomeworkGradeLevel.PASS],
|
|
67
|
+
[-62, HomeworkGradeLevel.EX],
|
|
68
|
+
[-61, HomeworkGradeLevel.EXEMPTION],
|
|
69
|
+
[-60, HomeworkGradeLevel.PASS],
|
|
70
|
+
[-59, HomeworkGradeLevel.FAILURE],
|
|
71
|
+
[-55, HomeworkGradeLevel.W],
|
|
72
|
+
[-51, HomeworkGradeLevel.I],
|
|
73
|
+
[-50, HomeworkGradeLevel.INCOMPLETE],
|
|
74
|
+
[-31, HomeworkGradeLevel.NA],
|
|
75
|
+
[-30, HomeworkGradeLevel.F],
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
export const JSONP_EXTRACTOR_NAME = 'thu_learn_lib_jsonp_extractor';
|
|
79
|
+
|
|
80
|
+
export function extractJSONPResult(jsonp: string): any {
|
|
81
|
+
// check jsonp format
|
|
82
|
+
if (!jsonp.startsWith(JSONP_EXTRACTOR_NAME)) {
|
|
83
|
+
throw FailReason.INVALID_RESPONSE;
|
|
84
|
+
}
|
|
85
|
+
// evaluate the result
|
|
86
|
+
// oxlint-disable-next-line typescript/no-implied-eval -- JSONP from the registrar is a JS expression, not JSON
|
|
87
|
+
return Function(`"use strict";const ${JSONP_EXTRACTOR_NAME}=(s)=>s;return ${jsonp};`)();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function formatFileSize(size: number): string {
|
|
91
|
+
// this logic is extracted from `judgeSize` function from Web Learning
|
|
92
|
+
if (size < 1024) return size + 'B';
|
|
93
|
+
if (size < 1024 * 1024) return (size / 1024).toFixed(2) + 'K';
|
|
94
|
+
if (size < 1024 * 1024 * 1024) return (size / 1024 / 1024).toFixed(2) + 'M';
|
|
95
|
+
return (size / 1024 / 1024 / 1024).toFixed(2) + 'G';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const CONTENT_TYPE_MAP = new Map([
|
|
99
|
+
[ContentType.NOTIFICATION, 'KCGG'],
|
|
100
|
+
[ContentType.FILE, 'KCKJ'],
|
|
101
|
+
[ContentType.HOMEWORK, 'KCZY'],
|
|
102
|
+
[ContentType.DISCUSSION, 'KCTL'],
|
|
103
|
+
[ContentType.QUESTION, 'KCDY'],
|
|
104
|
+
[ContentType.QUESTIONNAIRE, 'KCWJ'],
|
|
105
|
+
// omitted: 课表(KCKB)
|
|
106
|
+
]);
|
|
107
|
+
export const CONTENT_TYPE_MAP_REVERSE = new Map([
|
|
108
|
+
[CONTENT_TYPE_MAP.get(ContentType.NOTIFICATION)!, ContentType.NOTIFICATION],
|
|
109
|
+
[CONTENT_TYPE_MAP.get(ContentType.FILE)!, ContentType.FILE],
|
|
110
|
+
[CONTENT_TYPE_MAP.get(ContentType.HOMEWORK)!, ContentType.HOMEWORK],
|
|
111
|
+
[CONTENT_TYPE_MAP.get(ContentType.DISCUSSION)!, ContentType.DISCUSSION],
|
|
112
|
+
[CONTENT_TYPE_MAP.get(ContentType.QUESTION)!, ContentType.QUESTION],
|
|
113
|
+
[CONTENT_TYPE_MAP.get(ContentType.QUESTIONNAIRE)!, ContentType.QUESTIONNAIRE],
|
|
114
|
+
]);
|
|
115
|
+
|
|
116
|
+
export const QNR_TYPE_MAP = new Map([
|
|
117
|
+
['投票', QuestionnaireType.VOTE],
|
|
118
|
+
['填表', QuestionnaireType.FORM],
|
|
119
|
+
['问卷', QuestionnaireType.SURVEY],
|
|
120
|
+
]);
|