UNPKG

@maserde/ut-client

Version:

Universitas Terbuka API Client

165 lines (155 loc) 5.33 kB
import * as cheerio from 'cheerio'; import axios from 'axios'; const config = { BASE_URL: "https://elearning.ut.ac.id", }; axios.defaults.baseURL = config.BASE_URL; axios.defaults.validateStatus = (status) => { return status >= 200 && status < 400; }; // Libraries class Auth { getElementCsrf(parsedHtml) { return parsedHtml("input[name=logintoken]").first(); } getElementSessionKey(parsedHtml) { return parsedHtml("input[name=sesskey]").first(); } getSessionFromCookies(cookies) { if (!cookies) throw new Error(`Error parsing session from cookie, given empty cookies`); const filteredCookies = cookies.filter((cookie) => cookie.toLowerCase().indexOf("moodlesession") > -1); if (filteredCookies.length === 0) throw new Error(`No session found in cookies`); const sessionCookie = filteredCookies[0]; const session = sessionCookie.match(/MoodleSession=([^;]*)/); if (!session) throw new Error(`Error parsing session from cookie, invalid session cookie`); return session[1]; } getSession() { return new Promise(async (resolve, reject) => { try { const response = await axios(`${config.BASE_URL}/login/index.php`); const htmlText = await response.data; const cookies = response.headers["set-cookie"]; const session = this.getSessionFromCookies(cookies); const parsedHtml = cheerio.load(htmlText); const csrfToken = this.getElementCsrf(parsedHtml).val(); if (typeof csrfToken !== "string") throw new Error("CSRF token not found"); return resolve({ token: csrfToken, session, }); } catch (err) { return reject(err); } }); } async getToken(session = "") { try { const response = await axios("/my/", { headers: { cookie: `MoodleSession=${session}`, }, }); const htmlText = await response.data; const parsedHtml = cheerio.load(htmlText); const sessionKey = this.getElementSessionKey(parsedHtml).val(); if (typeof sessionKey !== "string") throw new Error("Session key not found"); return Promise.resolve(sessionKey); } catch (err) { return Promise.reject(err); } } async login(username, password) { try { const { token, session } = await this.getSession(); const response = await axios("/login/index.php", { headers: { "content-type": "application/x-www-form-urlencoded", cookie: `MoodleSession=${session}`, }, data: `anchor=&logintoken=${token}&username=${username}&password=${password}`, method: "POST", maxRedirects: 0, }); const isInvalidLogin = response.headers["location"] ? response.headers["location"].indexOf("testsession") === -1 : true; if (isInvalidLogin) throw new Error("Login failed, please check your username and password"); const cookies = response.headers["set-cookie"]; const authSession = this.getSessionFromCookies(cookies); const authKey = await this.getToken(authSession); return Promise.resolve({ session: authSession, key: authKey, }); } catch (err) { return Promise.reject(err); } } } class Course { getCourses() { console.log("Courses"); } } // Classes class ELearning { session = null; sessionKey = null; auth; course; credential = { username: "", password: "", }; constructor(options = {}) { this.auth = new Auth(); this.course = new Course(); if (options.session) { this.session = options.session; } if (options.credential) { this.credential.username = options.credential.username; this.credential.password = options.credential.password; } } isEmptySession() { return this.session === null; } async authenticate(credentials = { username: this.credential.username, password: this.credential.password, }) { const { session, key } = await this.auth.login(credentials.username, credentials.password); this.session = session; this.sessionKey = key; return Promise.resolve(this); } async getCourses() { return this.course.getCourses(); } } class App { constructor() { } createElearning(options = {}) { return new ELearning(options); } } const isNode = () => { return (typeof process !== "undefined" && process.versions != null && process.versions.node); }; if (!isNode()) throw new Error("This code should only be run in Node.js environment."); export { App as default }; //# sourceMappingURL=index.esm.js.map