UNPKG

magisterjs2

Version:

A JavaScript implementation of the Magister 6 API

756 lines (618 loc) 22.8 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.VersionInfo = exports.SchoolUtility = exports.School = exports.ProfileSettings = exports.ProfileInfo = exports.Privileges = exports.Person = exports.MessageFolder = exports.Message = exports.Magister = exports.GradeType = exports.GradePeriod = exports.Grade = exports.FileFolder = exports.File = exports.Course = exports.Class = exports.AuthError = exports.AssignmentVersion = exports.Assignment = exports.Appointment = exports.AddressInfo = exports.ActivityElement = exports.Activity = exports.AbsenceInfo = exports.VERSION = undefined; var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); exports.default = magister; exports.getSchools = getSchools; var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); var _nodeFetch = require('node-fetch'); var _nodeFetch2 = _interopRequireDefault(_nodeFetch); var _url = require('url'); var _url2 = _interopRequireDefault(_url); var _absenceInfo = require('./absenceInfo'); var _absenceInfo2 = _interopRequireDefault(_absenceInfo); var _activity = require('./activity'); var _activity2 = _interopRequireDefault(_activity); var _activityElement = require('./activityElement'); var _activityElement2 = _interopRequireDefault(_activityElement); var _appointment = require('./appointment'); var _appointment2 = _interopRequireDefault(_appointment); var _assignment = require('./assignment'); var _assignment2 = _interopRequireDefault(_assignment); var _assignmentVersion = require('./assignmentVersion'); var _assignmentVersion2 = _interopRequireDefault(_assignmentVersion); var _authError = require('./authError'); var _authError2 = _interopRequireDefault(_authError); var _class = require('./class'); var _class2 = _interopRequireDefault(_class); var _course = require('./course'); var _course2 = _interopRequireDefault(_course); var _file = require('./file'); var _file2 = _interopRequireDefault(_file); var _fileFolder = require('./fileFolder'); var _fileFolder2 = _interopRequireDefault(_fileFolder); var _grade = require('./grade'); var _grade2 = _interopRequireDefault(_grade); var _gradePeriod = require('./gradePeriod'); var _gradePeriod2 = _interopRequireDefault(_gradePeriod); var _gradeType = require('./gradeType'); var _gradeType2 = _interopRequireDefault(_gradeType); var _http = require('./http'); var _http2 = _interopRequireDefault(_http); var _message = require('./message'); var _message2 = _interopRequireDefault(_message); var _messageFolder = require('./messageFolder'); var _messageFolder2 = _interopRequireDefault(_messageFolder); var _person = require('./person'); var _person2 = _interopRequireDefault(_person); var _privileges = require('./privileges'); var _privileges2 = _interopRequireDefault(_privileges); var _profileInfo = require('./profileInfo'); var _profileInfo2 = _interopRequireDefault(_profileInfo); var _school = require('./school'); var _school2 = _interopRequireDefault(_school); var _schoolUtility = require('./schoolUtility'); var _schoolUtility2 = _interopRequireDefault(_schoolUtility); var _versionInfo = require('./versionInfo'); var _versionInfo2 = _interopRequireDefault(_versionInfo); var _util = require('./util'); var util = _interopRequireWildcard(_util); var _addressInfo = require('./addressInfo'); var _addressInfo2 = _interopRequireDefault(_addressInfo); var _profileSettings = require('./profileSettings'); var _profileSettings2 = _interopRequireDefault(_profileSettings); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // TODO: add nice warnings when trying to do stuff while not logged in yet /** * Class to communicate with Magister. * @private */ class Magister { /** * @param {Object} options * @param {School} school * @param {Http} http */ constructor(options, school, http) { var info = _url2.default.parse(school.url); if (!/^[a-z]+\.magister\.net$/.test(info.host)) { throw new Error('`school.url` is not a correct magister url'); } school.url = `https://${info.host}`; /** * @type Object * @readonly * @private */ this._options = options; /** * @type School * @readonly */ this.school = _lodash2.default.extend(new _school2.default({}), school); /** * @type Http * @readonly */ this.http = http; /** * @type ProfileInfo * @readonly */ this.profileInfo = null; } /** * @return {Promise<Activity[]>} */ activities() { var _this = this; return this._privileges.needs('activiteiten', 'read').then(function () { return _this.http.get(`${_this._personUrl}/activiteiten`); }).then(function (res) { return res.json(); }).then(function (res) { return res.Items.map(function (a) { return new _activity2.default(_this, a); }); }); } /** * @param {Date} from Time is ignored. * @param {Date} [to=from] Time is ignored * @param {Object} [options={}] * @param {Boolean} [options.fillPersons=false] * @param {Boolean} [options.fetchAbsences=true] * @param {Boolean} [options.ignoreAbsenceErrors=true] * @return {Promise<Appointment[]>} */ appointments() { var _this2 = this; // extract options var _ref = _lodash2.default.find(arguments, _lodash2.default.isPlainObject) || {}, _ref$fillPersons = _ref.fillPersons, fillPersons = _ref$fillPersons === undefined ? false : _ref$fillPersons, _ref$fetchAbsences = _ref.fetchAbsences, fetchAbsences = _ref$fetchAbsences === undefined ? true : _ref$fetchAbsences, _ref$ignoreAbsenceErr = _ref.ignoreAbsenceErrors, ignoreAbsenceErrors = _ref$ignoreAbsenceErr === undefined ? true : _ref$ignoreAbsenceErr; // extract dates var dates = (0, _lodash2.default)(arguments).filter(_lodash2.default.isDate).sortBy().value(); var from = dates[0]; var to = dates[1] || dates[0]; var fromUrl = util.urlDateConvert(from); var toUrl = util.urlDateConvert(to); // fetch appointments var appointmentsUrl = `${this._personUrl}/afspraken?van=${fromUrl}&tot=${toUrl}`; var appointmentsPromise = this._privileges.needs('afspraken', 'read').then(function () { return _this2.http.get(appointmentsUrl); }).then(function (res) { return res.json(); }).then(function (res) { return res.Items.map(function (a) { return new _appointment2.default(_this2, a); }); }).then(function (appointments) { if (!fillPersons) { return appointments; } var promises = appointments.map(function (a) { return Promise.all(a.teachers.map(function (t) { return t.getFilled('teacher'); })).then(function (teachers) { return a.teachers = teachers; }).then(function () { return a; }); }); return Promise.all(promises); }); // fetch absences var absencesPromise = Promise.resolve([]); if (fetchAbsences) { var absencesUrl = `${this._personUrl}/absenties?van=${fromUrl}&tot=${toUrl}`; absencesPromise = this._privileges.needs('Absenties', 'read').then(function () { return _this2.http.get(absencesUrl); }).then(function (res) { return res.json(); }).then(function (res) { return res.Items.map(function (a) { return new _absenceInfo2.default(_this2, a); }); }); if (ignoreAbsenceErrors) { absencesPromise = absencesPromise.catch(function () { return []; }); } } return Promise.all([appointmentsPromise, absencesPromise]).then(function (_ref2) { var _ref3 = _slicedToArray(_ref2, 2), appointments = _ref3[0], absences = _ref3[1]; var _loop = function _loop(a) { a.absenceInfo = absences.find(function (i) { return i.appointment.id === a.id; }); }; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = appointments[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var a = _step.value; _loop(a); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return appointments; }).then(function (appointments) { return _lodash2.default.sortBy(appointments, 'start'); }); } /** * @param {Object} [options={}] * @param {Number} [options.count=50] * @param {Number} [options.skip=0]] * @param {Boolean} [options.fillPersons=false] * @return {Promise<Assignment[]>} */ assignments() { var _this3 = this; var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref4$count = _ref4.count, count = _ref4$count === undefined ? 50 : _ref4$count, _ref4$skip = _ref4.skip, skip = _ref4$skip === undefined ? 0 : _ref4$skip, _ref4$fillPersons = _ref4.fillPersons, fillPersons = _ref4$fillPersons === undefined ? false : _ref4$fillPersons; var url = `${this._personUrl}/opdrachten?top=${count}&skip=${skip}&status=alle`; return this._privileges.needs('eloopdracht', 'read').then(function () { return _this3.http.get(url); }).then(function (res) { return res.json(); }).then(function (res) { return res.Items.map(function (i) { return i.Id; }); }).then(function (ids) { var promises = ids.map(function (id) { return _this3.http.get(`${_this3._personUrl}/opdrachten/${id}`).then(function (res) { return res.json(); }); }); return Promise.all(promises); }).then(function (items) { var promises = items.map(function (item) { var assignment = new _assignment2.default(_this3, item); if (!fillPersons) { return assignment; } return Promise.all(assignment.teachers.map(function (p) { return p.getFilled('teacher'); })).then(function (teachers) { return assignment.teachers = teachers; }).then(function () { return assignment; }); }); return Promise.all(promises); }); } /** * @return {Promise<Magister[]>} */ children() { var _this4 = this; if (this.profileInfo.isChild) { return Promise.reject(new Error('User is not a parent')); } return this.http.get(`${this._personUrl}/kinderen`).then(function (res) { return res.json(); }).then(function (res) { return res.Items; }).then(function (items) { return items.map(function (raw) { var m = Object.create(_this4); m.school = _this4.school; m.http = _this4.http; m._personUrl = `${_this4.school.url}/api/personen/${raw.Id}`; m._pupilUrl = `${_this4.school.url}/api/leerlingen/${raw.Id}`; m.profileInfo = new _profileInfo2.default(_this4, raw); return m; }); }); } /** * @return {Promise<Course>} */ courses() { var _this5 = this; return this._privileges.needs('aanmeldingen', 'read').then(function () { return _this5.http.get(`${_this5._personUrl}/aanmeldingen`); }).then(function (res) { return res.json(); }).then(function (res) { return res.Items.map(function (c) { return new _course2.default(_this5, c); }); }).then(function (items) { return _lodash2.default.sortBy(items, 'start'); }); } /** * @param {Object} options * @param {String} options.description The description of the appointment. * @param {Date} options.start The start of the appointment, time is * ignored when `options.fullDay` is set to true. * @param {Date} options.end The end of the appointment, this is ignored * when `options.fullDay` is set to true. * @param {Boolean} [options.fullDay=false] When this is true, * `options.end` is ignored and only `options.start` is used to set the * begin and the end for the appointment. * @param {String} [options.location] The location (classroom for example) * for the appointment. * @param {String} [options.content] Some arbitrary string you want to * save. * @param {Number} [options.type=1] The type of the appointment: 1 for * personal or 16 for planning * @return {Promise} */ createAppointment(options) { var _this6 = this; var required = ['description', 'start', 'end']; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = required[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var key = _step2.value; if (options[key] == null) { var err = new Error(`Not all required fields for \`options\` are given, required are: [ ${required.join(', ')} ]`); return Promise.reject(err); } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } if (options.fullDay) { options.start = util.date(options.start); options.end = new Date(options.start.getTime()) + 1000 * 60 * 60 * 24; } var payload = { Omschrijving: options.description, Start: options.start.toJSON(), Einde: options.end.toJSON(), Lokatie: _lodash2.default.trim(options.location), Inhoud: function () { var content = _lodash2.default.trim(options.content); return content.length > 0 ? _lodash2.default.escape(content) : null; }(), Type: options.type || 1, DuurtHeleDag: options.fullDay || false, // Static non-configurable stuff. InfoType: 0, WeergaveType: 1, Status: 2, HeeftBijlagen: false, Bijlagen: null, LesuurVan: null, LesuurTotMet: null, Aantekening: null, Afgerond: false, Vakken: null, Docenten: null, Links: null, Id: 0, Lokalen: null, Groepen: null, OpdrachtId: 0 }; return this._privileges.needs('afspraken', 'create').then(function () { return _this6.http.post(`${_this6._personUrl}/afspraken`, payload); }); } /** * @return {Promise<FileFolder[]>} */ fileFolders() { var _this7 = this; return this._privileges.needs('bronnen', 'read').then(function () { return _this7.http.get(`${_this7._personUrl}/bronnen?soort=0`); }).then(function (res) { return res.json(); }).then(function (res) { return res.Items.map(function (f) { return new _fileFolder2.default(_this7, f); }); }); } /** * @return {Promise<MessageFolder[]>} */ messageFolders() { var _this8 = this; return this._privileges.needs('berichten', 'read').then(function () { return _this8.http.get(`${_this8._personUrl}/berichten/mappen`); }).then(function (res) { return res.json(); }).then(function (res) { return res.Items.map(function (m) { return new _messageFolder2.default(_this8, m); }); }); } /** * @param {String} query * @param {String} [type] * @return {Promise<Person[]>} */ persons(query, type) { var _this9 = this; query = query != null ? query.trim() : ''; if (query.length < 3) { return Promise.resolve([]); } else if (type == null) { return Promise.all([this.persons(query, 'teacher'), this.persons(query, 'pupil')]).then(function (_ref5) { var _ref6 = _slicedToArray(_ref5, 2), teachers = _ref6[0], pupils = _ref6[1]; return teachers.concat(pupils); }); } type = { 'teacher': 'Personeel', 'pupil': 'Leerling', 'project': 'Project' }[type] || 'Overig'; query = query.replace(/ +/g, '+'); var url = `${this._personUrl}/contactpersonen?contactPersoonType=${type}&q=${query}`; return this._privileges.needs('contactpersonen', 'read').then(function () { return _this9.http.get(url); }).then(function (res) { return res.json(); }).then(function (res) { return res.Items.map(function (p) { p = new _person2.default(_this9, p); p._filled = true; return p; }); }); } schoolUtilities() { var _this10 = this; var url = `${this._personUrl}/lesmateriaal`; return this._privileges.needs('digitaallesmateriaal', 'read').then(function () { return _this10.http.get(url); }).then(function (res) { return res.json(); }).then(function (res) { return res.Items.map(function (u) { return new _schoolUtility2.default(_this10, u); }); }); } /** * Logins to Magister. * @param {Boolean} [forceLogin=false] Force a login, even when a session id * is in the options object. * @return {Promise<String>} A promise that resolves when done logging in. With the current session ID as parameter. */ login() { var _this11 = this; var forceLogin = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var setSessionId = function setSessionId(sessionId) { var cookie = `SESSION_ID=${sessionId}; M6UserName=${_this11._options.username}`; _this11.http._cookie = cookie; return sessionId; }; var options = this._options; var baseUrl = this.school.url; var deleteUrl = `${baseUrl}/api/sessies/huidige`; var postUrl = `${baseUrl}/api/sessies`; var promise = void 0; if (!forceLogin && options.sessionId) { promise = Promise.resolve(options.sessionId); } else { // delete the current session promise = this.http.delete(deleteUrl).then(function (r) { setSessionId(/[a-z\d-]+/.exec(r.headers.get('set-cookie'))[0]); // create a new session return _this11.http.post(postUrl, { Gebruikersnaam: options.username, Wachtwoord: options.password, IngelogdBlijven: options.keepLoggedIn }); }).then(function (r) { return (/[a-z\d-]+/.exec(r.headers.get('set-cookie'))[0] ); }).catch(function (err) { throw ['Ongeldig account of verkeerde combinatie van gebruikersnaam en wachtwoord. Probeer het nog eens of neem contact op met de applicatiebeheerder van de school.', 'Je gebruikersnaam en/of wachtwoord is niet correct.'].includes(err.message) ? new _authError2.default(err.message) : err; }); } return promise.then(setSessionId).then(function (sessionId) { return _this11.http.get(`${baseUrl}/api/account`).then(function (res) { return res.json(); }).then(function (res) { var id = res.Persoon.Id; // REVIEW: do we want to make profileInfo a function? _this11.profileInfo = new _profileInfo2.default(_this11, res.Persoon); _this11._privileges = new _privileges2.default(_this11, res.Groep[0].Privileges); _this11._personUrl = `${baseUrl}/api/personen/${id}`; _this11._pupilUrl = `${baseUrl}/api/leerlingen/${id}`; return sessionId; }); }); } } /** * Create a new Magister object using `options`. * @param {Object} options * @param {School} options.school The school to login to. * @param {String} [options.username] The username of the user to login to. * @param {String} [options.password] The password of the user to login to. * @param {String} [options.sessionId] The sessionId to use. (instead of the username and password) * @param {Boolean} [options.keepLoggedIn=true] Whether or not to keep the user logged in. * @param {Boolean} [options.login=true] Whether or not to call `Magister#login` before returning the object. * @return {Promise<Magister>} */ function magister(options) { _lodash2.default.defaults(options, { keepLoggedIn: true, login: true }); var rej = function rej(s) { return Promise.reject(new Error(s)); }; if (!(options.school && (options.sessionId || options.username && options.password))) { return rej('school and username&password or sessionId are required.'); } if (!_lodash2.default.isObject(options.school)) { return rej('school is not an object'); } else if (!_lodash2.default.isString(options.school.url)) { return rej('`school.url` is not a string'); } return Promise.resolve().then(function () { var m = new Magister(options, options.school, new _http2.default()); return options.login ? m.login().then(function () { return m; }) : m; }); } /** * Get the schools matching `query`. * @param {String} query * @return {Promise<School[]>} */ function getSchools(query) { query = query.replace(/\d/g, ''); query = query.trim(); query = query.replace(/ +/g, '+'); if (query.length < 3) { return Promise.resolve([]); } return (0, _nodeFetch2.default)(`https://mijn.magister.net/api/schools?filter=${query}`).then(function (res) { return res.json(); }).then(function (schools) { return schools.map(function (school) { return new _school2.default(school); }); }); } /** * The version of the library. * @type String * @readonly */ var VERSION = exports.VERSION = '2.0.0-alpha1.2'; exports.AbsenceInfo = _absenceInfo2.default; exports.Activity = _activity2.default; exports.ActivityElement = _activityElement2.default; exports.AddressInfo = _addressInfo2.default; exports.Appointment = _appointment2.default; exports.Assignment = _assignment2.default; exports.AssignmentVersion = _assignmentVersion2.default; exports.AuthError = _authError2.default; exports.Class = _class2.default; exports.Course = _course2.default; exports.File = _file2.default; exports.FileFolder = _fileFolder2.default; exports.Grade = _grade2.default; exports.GradePeriod = _gradePeriod2.default; exports.GradeType = _gradeType2.default; exports.Magister = Magister; exports.Message = _message2.default; exports.MessageFolder = _messageFolder2.default; exports.Person = _person2.default; exports.Privileges = _privileges2.default; exports.ProfileInfo = _profileInfo2.default; exports.ProfileSettings = _profileSettings2.default; exports.School = _school2.default; exports.SchoolUtility = _schoolUtility2.default; exports.VersionInfo = _versionInfo2.default;