@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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +324 -2
  3. package/lib/auth.d.ts +11 -0
  4. package/lib/auth.d.ts.map +1 -0
  5. package/lib/auth.js +99 -0
  6. package/lib/auth.js.map +1 -0
  7. package/lib/calendar.d.ts +16 -0
  8. package/lib/calendar.d.ts.map +1 -0
  9. package/lib/calendar.js +81 -0
  10. package/lib/calendar.js.map +1 -0
  11. package/lib/contents.d.ts +9 -0
  12. package/lib/contents.d.ts.map +1 -0
  13. package/lib/contents.js +52 -0
  14. package/lib/contents.js.map +1 -0
  15. package/lib/courses.d.ts +9 -0
  16. package/lib/courses.d.ts.map +1 -0
  17. package/lib/courses.js +82 -0
  18. package/lib/courses.js.map +1 -0
  19. package/lib/discussions.d.ts +11 -0
  20. package/lib/discussions.d.ts.map +1 -0
  21. package/lib/discussions.js +56 -0
  22. package/lib/discussions.js.map +1 -0
  23. package/lib/favorites.d.ts +35 -0
  24. package/lib/favorites.d.ts.map +1 -0
  25. package/lib/favorites.js +150 -0
  26. package/lib/favorites.js.map +1 -0
  27. package/lib/files.d.ts +13 -0
  28. package/lib/files.d.ts.map +1 -0
  29. package/lib/files.js +167 -0
  30. package/lib/files.js.map +1 -0
  31. package/lib/homework.d.ts +9 -0
  32. package/lib/homework.d.ts.map +1 -0
  33. package/lib/homework.js +193 -0
  34. package/lib/homework.js.map +1 -0
  35. package/lib/index.d.ts +105 -0
  36. package/lib/index.d.ts.map +1 -0
  37. package/lib/index.js +181 -0
  38. package/lib/index.js.map +1 -0
  39. package/lib/notices.d.ts +6 -0
  40. package/lib/notices.d.ts.map +1 -0
  41. package/lib/notices.js +84 -0
  42. package/lib/notices.js.map +1 -0
  43. package/lib/questionnaires.d.ts +7 -0
  44. package/lib/questionnaires.d.ts.map +1 -0
  45. package/lib/questionnaires.js +62 -0
  46. package/lib/questionnaires.js.map +1 -0
  47. package/lib/request.d.ts +31 -0
  48. package/lib/request.d.ts.map +1 -0
  49. package/lib/request.js +90 -0
  50. package/lib/request.js.map +1 -0
  51. package/lib/types.d.ts +392 -0
  52. package/lib/types.d.ts.map +1 -0
  53. package/lib/types.js +97 -0
  54. package/lib/types.js.map +1 -0
  55. package/lib/urls.d.ts +78 -0
  56. package/lib/urls.d.ts.map +1 -0
  57. package/lib/urls.js +160 -0
  58. package/lib/urls.js.map +1 -0
  59. package/lib/user.d.ts +7 -0
  60. package/lib/user.d.ts.map +1 -0
  61. package/lib/user.js +22 -0
  62. package/lib/user.js.map +1 -0
  63. package/lib/utils.d.ts +13 -0
  64. package/lib/utils.d.ts.map +1 -0
  65. package/lib/utils.js +115 -0
  66. package/lib/utils.js.map +1 -0
  67. package/package.json +67 -4
  68. package/src/auth.ts +121 -0
  69. package/src/calendar.ts +102 -0
  70. package/src/contents.ts +67 -0
  71. package/src/courses.ts +97 -0
  72. package/src/discussions.ts +80 -0
  73. package/src/favorites.ts +167 -0
  74. package/src/files.ts +197 -0
  75. package/src/homework.ts +279 -0
  76. package/src/index.ts +282 -0
  77. package/src/notices.ts +110 -0
  78. package/src/questionnaires.ts +76 -0
  79. package/src/request.ts +101 -0
  80. package/src/types.ts +445 -0
  81. package/src/urls.ts +257 -0
  82. package/src/user.ts +28 -0
  83. 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
+ ]);