
Product
Introducing Reports: An Extensible Reporting Framework for Socket Data
Explore exportable charts for vulnerabilities, dependencies, and usage with Reports, Socket’s new extensible reporting framework.
thu-learn-lib
Advanced tools
a JavaScript library to provide a program-friendly interface to Web Learning (2018) of Tsinghua University
This is a JavaScript library aimed to provide a program-friendly interface of web Learning of Tsinghua University.
This project is licensed under MIT License.
pnpm add thu-learn-lib
<script src="https://cdn.jsdelivr.net/npm/thu-learn-lib@3"></script>
<!-- or -->
<script src="https://unpkg.com/thu-learn-lib@3"></script>
The library is exposed under window.LearnLib.
<script type="module">
import { Learn2018Helper } from 'https://esm.sh/thu-learn-lib@3';
</script>
pnpm run build
You can find the bundled library in lib/.
index.js: ES module entryindex.d.ts: definition file for TypeScriptindex.iife.js{,.map}: IIFE for use in browser (with source map for debugging)With the new authentication method adopted by Web Learning, you must provide a fingerPrint to log in at the moment. You can get it by going through the authentication process either in a browser (or a WebView) or programmatically (see thu-info-lib).
Using a web context is recommended, so you do not need to deal with the two-factor authentication manually. Currently, you can get the fingerPrint by running fingerprintUtil.getFingers() in the ID page, or by intercepting the request to https://id.tsinghua.edu.cn/do/off/ui/auth/login/check and extracting it from the request body. Note that the fingerPrint is valid and can be used for future login only after the authentication process fully completes.
import { Learn2018Helper } from 'thu-learn-lib';
// There are three ways of logging in:
// 1. provide nothing, but invoking login manually with username, password and fingerPrint
const helper = new Learn2018Helper();
// 2. provide a CredentialProvider function, which can be async
const helper = new Learn2018Helper({
provider: () => ({ username, password, fingerPrint }),
});
// Note that by using the following two methods you may encounter problems like login time out.
// But if you provide a credential provider, the library will retry logging in when failing, automatically resolving the cookie expiry problem.
// So we strongly recommend using this method.
// If you do not provide a cookie jar or CredentialProvider, you must log in manually. Otherwise you do not need to call login explicitly.
try {
await helper.login(username, password, fingerPrint);
} catch (e) {
// e is a FailReason
}
// Logout if you want, but the cookie jar will not be cleared.
await helper.logout();
We currently support both student and teacher (or TA) version of web learning. To keep backwards compatibility, the default behavior of all APIs is to use the student version. The following APIs needs CourseType.TEACHER as the last (optional) parameter to access the teacher version. You should use them when you are the teacher / TA of one course, for you will get nothing from the student version in that case.
We do not maintain a global type in Learn2018Helper class, for there can be the situation that one can be a student and teacher of the same course simultaneously, on which by using different CourseType you can get different results.
getCourseListgetNotificationList/getFileList/getHomeworkList/getDiscussionList/getAnsweredQuestionListgetAllContentsNote that currently fetching homework information from teacher version is partially implemented.
import { ContentType, ApiError } from 'thu-learn-lib';
// get ids of all semesters that current account has access to
const semesters = await helper.getSemesterIdList();
// get get semester info
const semester = await helper.getCurrentSemester();
// get courses of this semester
const courses = await helper.getCourseList(semester.id);
const course = courses[0];
// get detail information about the course
const discussions = await helper.getDiscussionList(course.id);
const notifications = await helper.getNotificationList(course.id);
const files = await helper.getFileList(course.id);
const homework = await helper.getHomeworkList(course.id);
const questions = await helper.getAnsweredQuestionList(course.id);
// get content from bunches of courses
// the return type will be { [id: string]: Content }
// where Content = Notification | File | Homework | Discussion | Question
const homeworks = await helper.getAllContents([1, 2, 3], ContentType.HOMEWORK);
// get course calendar in a period
try {
const calendar = await helper.getCalendar('20191001', '20191201');
} catch (e) {
const error = e as ApiError;
// check e.reason and e.extra for information
// you might want to check your date format or shrink the range (currently we observe a limit of 29 days)
}
According to security strategies (CORS, CORB) of browsers, you might need to run the code in the page context of https://learn.tsinghua.edu.cn and https://id.tsinghua.edu.cn. The simplest way is to run the code in Node.js or in browser extension.
See src/types.ts for type definitions. Note that ApiError represents the type that will be used in rejected Promises.
Run pnpm run test for testing. It requires your personal credential since we don't have mocks for these APIs. To do this, you must touch a .env similar to template.env under /test folder.
It's ok if you meet Timeout * Async callback was not invoked within the 5000ms timeout... error when running tests, rerun tests may resolve this problem. If you hate this, just add the third argument timeout to every testcase it("should...", async () => void, timeout) and make sure it's greater than 5000.
HomeworkCompletionTypeentities to 4.5.0 to reduce binary sizegetQuestionnaireList API and some public types)studentHomeworkIdsetCSRFToken function to manually reuse previous (maybe valid) token and prevent unnecessary re-login (see #49)
Note: To use this feature in Node.js, cookieJar should also be reused, otherwise it will not work. (not the case in browser env)CourseContent type: default value for type param T (breaking change introduced in #53)File.id2 added in previous version to actual id and previously used id to fileId (see #60)FileCategory type and optional category field in File typegetFileList function automatically fetches all categories and saves them in each File objectgetFileCategoryList function to fetch file categoriesgetFileListByCategory function to get file list by categoryCourseType.TEACHERHomework.gradeLevel changed to HomeworkGradeLevel (a string enum) for better i18nfetch-cookie dependency in browser build, reducing bundle sizegetUserInfo interface (#48, thanks to @robertying)webpack -> tsupwebpack -> vitejest -> vitestcross-fetch -> node-fetch-native (Node.js now has native fetch)real-isomorphic-fetch -> fetch-cookie (fetch-cookie now can handle redirects)tough-cookie-no-native -> tough-cookie (tough-cookie is now native)/lib or /lib/types anymorefake-parse5 to a seperate librarygeneratePreviewUrlForFirstPage to switch preview URL type (default to true)RemoteFile to represent a file on Web LearningallowFailure in getAllContents for conveniencegetCSRFToken methodaddCSRFTokenToUrl function as API for convenienceimport in Node.jsparse5 with htmlparser2 in Cheerio and remove it from bundled file (replaced with src/fake-parse5)v2.3.1 (not published) and v2.3.0 that build output fails to be uploaded to npmApiError in usage of Promise.reject (might be a breaking change)previewUrlLearn2018Helper class to protect credentialspreviewUrl to Fileeval in getCalendarFailReason to represent all strings that will be used as the reason of rejected Promiseslogin and logout no longer return PromisesCredentialProvider is provided (thanks to mayeths)jest (thanks to mayeths)null values in getSemesterIdList APIhttps://learn.tsinghua.edu.cn/ from learn2018 permanentlygetTACourseList to get TA's course list (temporarily can not be used by other functions)js-base64 backBase64.js instead of js-base64, which uses evil evalyarnattachmentUrl filed of Notificationurl for Courseurl for Question (to display correct section name)url error in Questiondescription field of homeworkentities to decode HTML entitiesFAQs
a JavaScript library to provide a program-friendly interface to Web Learning (2018) of Tsinghua University
We found that thu-learn-lib demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Explore exportable charts for vulnerabilities, dependencies, and usage with Reports, Socket’s new extensible reporting framework.

Product
Socket for Jira lets teams turn alerts into Jira tickets with manual creation, automated ticketing rules, and two-way sync.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.