@maserde/ut-client
Version:
Universitas Terbuka API Client
165 lines (155 loc) • 5.33 kB
JavaScript
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