├── test ├── .eslintrc ├── fixtures │ ├── bells.json │ ├── lessons-count.json │ ├── files.json │ ├── bagrut-grades.json │ ├── groups.json │ ├── schools.json │ ├── grades.json │ ├── timetable.json │ ├── contacts.json │ ├── online-lessons.json │ ├── login.json │ ├── behave.json │ └── conversations.json ├── client.js ├── fetch-schools.js ├── bells.js ├── files.js ├── grades.js ├── groups.js ├── behave.js ├── timetable.js ├── online-lessons.js ├── bagrut-grades.js ├── lessons-count.js ├── utils.js ├── login.js ├── contacts.js └── conversations.js ├── .gitignore ├── src ├── index.js ├── controllers │ ├── logout.js │ ├── bells.js │ ├── groups.js │ ├── lessons-count.js │ ├── bagrut-grades.js │ ├── files.js │ ├── timetable.js │ ├── grades.js │ ├── online-lessons.js │ ├── behave.js │ ├── contacts.js │ ├── login.js │ └── conversations.js ├── fetch-schools.js ├── utils.js ├── api-config.js ├── index.test-d.ts ├── index.d.ts └── client.js ├── jest.config.js ├── .eslintrc ├── .babelrc ├── .editorconfig ├── .github └── workflows │ ├── publish.yml │ └── test.yml ├── webpack.config.babel.js ├── LICENSE ├── package.json └── README.md /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jest": true 4 | } 5 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | npm-debug.log 4 | yarn-error.log 5 | coverage 6 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import fetchSchools from './fetch-schools'; 2 | import Client from './client'; 3 | 4 | export { fetchSchools, Client }; 5 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testMatch: [ 3 | '**/test/**/*.js?(x)', 4 | '**/?(*.)(spec|test).js?(x)', 5 | ], 6 | verbose: true, 7 | }; 8 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": "airbnb-base", 4 | "rules": { 5 | "no-plusplus": 0, 6 | "no-underscore-dangle": 0 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/controllers/logout.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../api-config'; 2 | 3 | const logoutController = axios => 4 | axios.get(endpoints.logout); 5 | 6 | export default logoutController; 7 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env" 4 | ], 5 | "env": { 6 | "test": { 7 | "plugins": ["@babel/plugin-transform-runtime"] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /test/fixtures/bells.json: -------------------------------------------------------------------------------- 1 | { 2 | "plain": [{ 3 | "lessonNumber": 1, 4 | "startTime": "08:15:00", 5 | "endTime": "09:00:00" 6 | }], 7 | "parsed": [{ 8 | "lesson": 1, 9 | "startTime": "08:15:00", 10 | "endTime": "09:00:00" 11 | }] 12 | } 13 | -------------------------------------------------------------------------------- /test/fixtures/lessons-count.json: -------------------------------------------------------------------------------- 1 | { 2 | "plain": [{ 3 | "groupId": 1000, 4 | "lessonCount": 10, 5 | "studentGuid": "0000", 6 | "weeklyHours": 6 7 | }], 8 | "parsed": [{ 9 | "groupId": 1000, 10 | "lessonCount": 10, 11 | "weeklyHours": 6 12 | }] 13 | } 14 | -------------------------------------------------------------------------------- /test/client.js: -------------------------------------------------------------------------------- 1 | import Client from '../src/client'; 2 | 3 | test('should reject if user is not logged', (done) => { 4 | const client = new Client(); 5 | 6 | client.getGrades().catch((err) => { 7 | expect(err.message).toEqual('User is not logged in'); 8 | done(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/fixtures/files.json: -------------------------------------------------------------------------------- 1 | { 2 | "plain": [{ 3 | "fileId": 10, 4 | "fileName": "File.txt", 5 | "ownerGroup": "Group1" 6 | }], 7 | "parsed": [{ 8 | "id": 10, 9 | "name": "File.txt", 10 | "groupName": "Group1", 11 | "url": "https://web.mashov.info/api/students/0000/files/10/File.txt" 12 | }] 13 | } 14 | -------------------------------------------------------------------------------- /src/controllers/bells.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../api-config'; 2 | 3 | const bellsController = axios => 4 | axios.get(endpoints.bells) 5 | .then(response => response.data) 6 | .then(data => data.map(e => ({ 7 | lesson: e.lessonNumber, 8 | startTime: e.startTime, 9 | endTime: e.endTime, 10 | }))); 11 | 12 | export default bellsController; 13 | -------------------------------------------------------------------------------- /test/fixtures/bagrut-grades.json: -------------------------------------------------------------------------------- 1 | { 2 | "plain": [{ 3 | "studentGuid":"0000", 4 | "moed": 201706, 5 | "semel": 1001, 6 | "name": "Subject1", 7 | "shnaty": 100, 8 | "test": 100, 9 | "final": 100 10 | }], 11 | "parsed": [{ 12 | "id": 1001, 13 | "name": "Subject1", 14 | "yearly": 100, 15 | "test": 100, 16 | "final": 100 17 | }] 18 | } 19 | -------------------------------------------------------------------------------- /test/fixtures/groups.json: -------------------------------------------------------------------------------- 1 | { 2 | "plain": [{ 3 | "fullSubjectName": "FullSubject1", 4 | "groupId": 1000, 5 | "groupName": "Group1", 6 | "subjectName": "Subject1", 7 | "teacherGuid": "0000", 8 | "teacherName": "Teacher1" 9 | }], 10 | "parsed": [{ 11 | "id": 1000, 12 | "name": "Group1", 13 | "subject": "Subject1", 14 | "teacher": "Teacher1" 15 | }] 16 | } 17 | -------------------------------------------------------------------------------- /src/controllers/groups.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../api-config'; 2 | 3 | const groupsController = (axios, payload) => 4 | axios.get(endpoints.groups(payload.userId)) 5 | .then(response => response.data) 6 | .then(data => data.map(e => ({ 7 | id: e.groupId, 8 | name: e.groupName, 9 | subject: e.subjectName, 10 | teacher: e.teacherName, 11 | }))); 12 | 13 | export default groupsController; 14 | -------------------------------------------------------------------------------- /test/fixtures/schools.json: -------------------------------------------------------------------------------- 1 | { 2 | "plain": [ 3 | { "semel": 1000, "name": "s1", "years": [2017] }, 4 | { "semel": 1001, "name": "s2", "years": [2015, 2017] }, 5 | { "semel": 1002, "name": "s3", "years": [2028] } 6 | ], 7 | "parsed": [ 8 | { "id": 1000, "name": "s1", "years": [2017] }, 9 | { "id": 1001, "name": "s2", "years": [2015, 2017] }, 10 | { "id": 1002, "name": "s3", "years": [2028] } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/controllers/lessons-count.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../api-config'; 2 | 3 | const lessonsCountController = (axios, payload) => 4 | axios.get(endpoints.lessonsCount(payload.userId)) 5 | .then(response => response.data) 6 | .then(data => data.map(e => ({ 7 | groupId: e.groupId, 8 | lessonCount: e.lessonCount, 9 | weeklyHours: e.weeklyHours, 10 | }))); 11 | 12 | export default lessonsCountController; 13 | -------------------------------------------------------------------------------- /src/controllers/bagrut-grades.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../api-config'; 2 | 3 | const bagrutGradesController = (axios, payload) => 4 | axios.get(endpoints.bagrutGrades(payload.userId)) 5 | .then(response => response.data) 6 | .then(data => data.map(e => ({ 7 | id: e.semel, 8 | name: e.name, 9 | yearly: e.shnaty, 10 | test: e.test, 11 | final: e.final, 12 | }))); 13 | 14 | export default bagrutGradesController; 15 | -------------------------------------------------------------------------------- /src/fetch-schools.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { endpoints } from './api-config'; 3 | 4 | /** 5 | * Fetch public list of schools. 6 | * 7 | * @returns {Promise} 8 | */ 9 | const fetchSchools = () => 10 | axios.get(endpoints.schools) 11 | .then(response => response.data) 12 | .then(schools => schools.map(s => ({ 13 | id: s.semel, 14 | name: s.name, 15 | years: s.years, 16 | }))); 17 | 18 | export default fetchSchools; 19 | -------------------------------------------------------------------------------- /test/fixtures/grades.json: -------------------------------------------------------------------------------- 1 | { 2 | "plain": [{ 3 | "teacherName": "Teacher1", 4 | "groupId": 100000, 5 | "subjectName":"sn1", 6 | "eventDate": "0000-00-00T00:00:00", 7 | "gradingEvent": "first exam", 8 | "gradeType": "exam", 9 | "grade": 100 10 | }], 11 | "parsed": [{ 12 | "teacher": "Teacher1", 13 | "groupId": 100000, 14 | "subject": "sn1", 15 | "date": "0000-00-00T00:00:00", 16 | "type": "exam", 17 | "event": "first exam", 18 | "grade": 100 19 | }] 20 | } 21 | -------------------------------------------------------------------------------- /src/controllers/files.js: -------------------------------------------------------------------------------- 1 | import encodeUrl from 'encodeurl'; 2 | import { endpoints } from '../api-config'; 3 | 4 | const filesController = (axios, payload) => 5 | axios.get(endpoints.files.all(payload.userId)) 6 | .then(response => response.data) 7 | .then(data => data.map(e => ({ 8 | id: e.fileId, 9 | name: e.fileName, 10 | groupName: e.ownerGroup, 11 | url: encodeUrl(endpoints.files.single(payload.userId, e.fileId, e.fileName)), 12 | }))); 13 | 14 | export default filesController; 15 | -------------------------------------------------------------------------------- /src/controllers/timetable.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../api-config'; 2 | 3 | const timetableController = (axios, payload) => 4 | axios.get(endpoints.timetable(payload.userId)) 5 | .then(response => response.data) 6 | .then(data => data.map(e => ({ 7 | groupId: e.timeTable.groupId, 8 | day: e.timeTable.day, 9 | lesson: e.timeTable.lesson, 10 | subject: e.groupDetails.subjectName, 11 | teacher: e.groupDetails.teacherName, 12 | }))); 13 | 14 | export default timetableController; 15 | -------------------------------------------------------------------------------- /src/controllers/grades.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../api-config'; 2 | 3 | const gradesController = (axios, payload) => 4 | axios.get(endpoints.grades(payload.userId)) 5 | .then(response => response.data) 6 | .then(data => data.map(e => ({ 7 | teacher: e.teacherName, 8 | groupId: e.groupId, 9 | subject: e.subjectName, 10 | date: e.eventDate, 11 | type: e.gradeType, 12 | event: e.gradingEvent, 13 | grade: e.grade, 14 | }))); 15 | 16 | export default gradesController; 17 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | build-test-and-publish: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v1 12 | - uses: actions/setup-node@v1 13 | with: 14 | node-version: 12 15 | registry-url: 'https://registry.npmjs.org' 16 | 17 | - run: | 18 | npm ci 19 | npm test 20 | 21 | - run: npm publish 22 | env: 23 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 24 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: push 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | 9 | strategy: 10 | matrix: 11 | node-version: [8.x, 10.x, 12.x] 12 | 13 | steps: 14 | - uses: actions/checkout@v1 15 | 16 | - name: Use Node.js ${{ matrix.node-version }} 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: ${{ matrix.node-version }} 20 | 21 | - run: | 22 | npm ci 23 | npm run build --if-present 24 | npm test 25 | -------------------------------------------------------------------------------- /src/controllers/online-lessons.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../api-config'; 2 | 3 | const onlineLessonsController = axios => 4 | axios.get(endpoints.onlineLessons.all) 5 | .then(response => response.data) 6 | .then(data => data.map(e => ({ 7 | lessonId: e.confid || e.confId, 8 | name: e.name, 9 | teacher: e.creatorName, 10 | startTime: e.startDate, 11 | endTime: e.endDate, 12 | joinLink: endpoints.onlineLessons.join(e.confid || e.confId), 13 | }))); 14 | 15 | export default onlineLessonsController; 16 | -------------------------------------------------------------------------------- /src/controllers/behave.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../api-config'; 2 | 3 | const behaveController = (axios, payload) => 4 | axios.get(endpoints.behave(payload.userId)) 5 | .then(response => response.data) 6 | .then(data => data.map(e => ({ 7 | groupId: e.groupId, 8 | lesson: e.lesson, 9 | date: e.lessonDate, 10 | type: e.achvaName, 11 | justification: e.justification, 12 | justificationId: e.justificationId, 13 | reporter: e.reporter, 14 | subject: e.subject, 15 | }))); 16 | 17 | export default behaveController; 18 | -------------------------------------------------------------------------------- /test/fixtures/timetable.json: -------------------------------------------------------------------------------- 1 | { 2 | "plain": [{ 3 | "timeTable": { 4 | "groupId": 1000, 5 | "day": 1, 6 | "lesson": 2, 7 | "roomNum": "Classroom1" 8 | }, 9 | "groupDetails": { 10 | "fullSubjectName": "FullSubject1", 11 | "groupId": 1000, 12 | "groupName": "Group1", 13 | "subjectName": "Subject1", 14 | "teacherGuid": "0000", 15 | "teacherName": "Teacher1" 16 | } 17 | }], 18 | "parsed": [{ 19 | "groupId": 1000, 20 | "day": 1, 21 | "lesson": 2, 22 | "subject": "Subject1", 23 | "teacher": "Teacher1" 24 | }] 25 | } 26 | -------------------------------------------------------------------------------- /test/fetch-schools.js: -------------------------------------------------------------------------------- 1 | import moxios from 'moxios'; 2 | import { endpoints } from '../src/api-config'; 3 | import fetchSchools from '../src/fetch-schools'; 4 | import schoolsFixture from './fixtures/schools.json'; 5 | 6 | beforeEach(() => { 7 | moxios.install(); 8 | }); 9 | 10 | afterEach(() => { 11 | moxios.uninstall(); 12 | }); 13 | 14 | test('should fetch a list of all schools', async () => { 15 | moxios.stubRequest(endpoints.schools, { 16 | status: 200, 17 | response: schoolsFixture.plain, 18 | }); 19 | 20 | const schools = await fetchSchools(); 21 | expect(schools).toMatchObject(schoolsFixture.parsed); 22 | }); 23 | -------------------------------------------------------------------------------- /test/fixtures/contacts.json: -------------------------------------------------------------------------------- 1 | { 2 | "plain": [{ 3 | "studentGuid": "0000", 4 | "familyName": "Doe", 5 | "privateName": "John", 6 | "classCode": "11th", 7 | "classNum": 2, 8 | "city": "Gotham", 9 | "address": "Street", 10 | "phone": "080000000", 11 | "email": "hello@example.com", 12 | "cellphone": "0500000000" 13 | }], 14 | "parsed": [{ 15 | "firstName": "John", 16 | "lastName": "Doe", 17 | "classCode": "11th", 18 | "classNumber": 2, 19 | "city": "Gotham", 20 | "address": "Street", 21 | "email": "hello@example.com", 22 | "phone": "080000000", 23 | "cellphone": "0500000000" 24 | }] 25 | } 26 | -------------------------------------------------------------------------------- /test/fixtures/online-lessons.json: -------------------------------------------------------------------------------- 1 | { 2 | "plain": [ 3 | { 4 | "confId": 100000, 5 | "confid": 100000, 6 | "creationDate": "0000-00-00T00:00:00", 7 | "creatorName": "Teacher1", 8 | "endDate": "0000-00-00T00:00:00", 9 | "isModerator": false, 10 | "name": "Subject1", 11 | "startDate": "0000-00-00T00:00:00" 12 | } 13 | ], 14 | "parsed": [ 15 | { 16 | "lessonId": 100000, 17 | "name": "Subject1", 18 | "teacher": "Teacher1", 19 | "startTime": "0000-00-00T00:00:00", 20 | "endTime": "0000-00-00T00:00:00", 21 | "joinLink": "https://web.mashov.info/api/bbb/join/100000" 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /test/fixtures/login.json: -------------------------------------------------------------------------------- 1 | { 2 | "plain": { 3 | "sessionId": "0000", 4 | "credential": { 5 | "sessionId": "0000", 6 | "userId": "0000", 7 | "idNumber": 123456789, 8 | "userType": 0, 9 | "schoolUserType": 1, 10 | "hasAuthenticated": true, 11 | "semel": 1000, 12 | "year": 2017, 13 | "correlationId": "0000" 14 | }, 15 | "accessToken": { 16 | "username": null, 17 | "displayName": "John Doe 11th(2)" 18 | } 19 | }, 20 | "headers": { 21 | "x-csrf-token": "0000", 22 | "set-cookie": [ 23 | "MashovAuthToken=0000; secure", 24 | "uniquId=0000; secure", 25 | "Csrf-Token=0000; secure" 26 | ] 27 | } 28 | } -------------------------------------------------------------------------------- /test/bells.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import moxios from 'moxios'; 3 | import { endpoints } from '../src/api-config'; 4 | import bellsController from '../src/controllers/bells'; 5 | import bellsFixture from './fixtures/bells.json'; 6 | 7 | beforeEach(() => { 8 | moxios.install(); 9 | }); 10 | 11 | afterEach(() => { 12 | moxios.uninstall(); 13 | }); 14 | 15 | test('should return all bells events', (done) => { 16 | moxios.stubRequest(endpoints.bells, { 17 | status: 200, 18 | response: bellsFixture.plain, 19 | }); 20 | 21 | bellsController(axios, { 22 | userId: '0000', 23 | }).then((bells) => { 24 | expect(bells).toMatchObject(bellsFixture.parsed); 25 | done(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/files.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import moxios from 'moxios'; 3 | import { endpoints } from '../src/api-config'; 4 | import filesController from '../src/controllers/files'; 5 | import filesFixture from './fixtures/files.json'; 6 | 7 | beforeEach(() => { 8 | moxios.install(); 9 | }); 10 | 11 | afterEach(() => { 12 | moxios.uninstall(); 13 | }); 14 | 15 | test('should return all files', (done) => { 16 | moxios.stubRequest(endpoints.files.all('0000'), { 17 | status: 200, 18 | response: filesFixture.plain, 19 | }); 20 | 21 | filesController(axios, { 22 | userId: '0000', 23 | }).then((files) => { 24 | expect(files).toMatchObject(filesFixture.parsed); 25 | done(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/grades.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import moxios from 'moxios'; 3 | import { endpoints } from '../src/api-config'; 4 | import gradesController from '../src/controllers/grades'; 5 | import gradesFixture from './fixtures/grades.json'; 6 | 7 | beforeEach(() => { 8 | moxios.install(); 9 | }); 10 | 11 | afterEach(() => { 12 | moxios.uninstall(); 13 | }); 14 | 15 | test('should return all grades', (done) => { 16 | moxios.stubRequest(endpoints.grades('0000'), { 17 | status: 200, 18 | response: gradesFixture.plain, 19 | }); 20 | 21 | gradesController(axios, { 22 | userId: '0000', 23 | }).then((grades) => { 24 | expect(grades).toMatchObject(gradesFixture.parsed); 25 | done(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/groups.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import moxios from 'moxios'; 3 | import { endpoints } from '../src/api-config'; 4 | import groupsController from '../src/controllers/groups'; 5 | import groupsFixture from './fixtures/groups.json'; 6 | 7 | beforeEach(() => { 8 | moxios.install(); 9 | }); 10 | 11 | afterEach(() => { 12 | moxios.uninstall(); 13 | }); 14 | 15 | test('should return all groups', (done) => { 16 | moxios.stubRequest(endpoints.groups('0000'), { 17 | status: 200, 18 | response: groupsFixture.plain, 19 | }); 20 | 21 | groupsController(axios, { 22 | userId: '0000', 23 | }).then((groups) => { 24 | expect(groups).toMatchObject(groupsFixture.parsed); 25 | done(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/behave.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import moxios from 'moxios'; 3 | import { endpoints } from '../src/api-config'; 4 | import behaveController from '../src/controllers/behave'; 5 | import behaveFixture from './fixtures/behave.json'; 6 | 7 | beforeEach(() => { 8 | moxios.install(); 9 | }); 10 | 11 | afterEach(() => { 12 | moxios.uninstall(); 13 | }); 14 | 15 | test('should return all behave events', (done) => { 16 | moxios.stubRequest(endpoints.behave('0000'), { 17 | status: 200, 18 | response: behaveFixture.plain, 19 | }); 20 | 21 | behaveController(axios, { 22 | userId: '0000', 23 | }).then((behave) => { 24 | expect(behave).toMatchObject(behaveFixture.parsed); 25 | done(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/timetable.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import moxios from 'moxios'; 3 | import { endpoints } from '../src/api-config'; 4 | import timetableController from '../src/controllers/timetable'; 5 | import timetableFixture from './fixtures/timetable.json'; 6 | 7 | beforeEach(() => { 8 | moxios.install(); 9 | }); 10 | 11 | afterEach(() => { 12 | moxios.uninstall(); 13 | }); 14 | 15 | test('should return all timetable events', (done) => { 16 | moxios.stubRequest(endpoints.timetable('0000'), { 17 | status: 200, 18 | response: timetableFixture.plain, 19 | }); 20 | 21 | timetableController(axios, { 22 | userId: '0000', 23 | }).then((timetable) => { 24 | expect(timetable).toMatchObject(timetableFixture.parsed); 25 | done(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /src/controllers/contacts.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../api-config'; 2 | 3 | const transformContactsData = data => data.map(e => ({ 4 | firstName: e.privateName, 5 | lastName: e.familyName, 6 | classCode: e.classCode, 7 | classNumber: e.classNum, 8 | city: e.city, 9 | address: e.address, 10 | email: e.email, 11 | phone: e.phone, 12 | cellphone: e.cellphone, 13 | })); 14 | 15 | const student = (axios, payload) => 16 | axios.get(endpoints.contacts.student(payload.userId)) 17 | .then(response => response.data) 18 | .then(transformContactsData); 19 | 20 | const group = (axios, payload) => 21 | axios.get(endpoints.contacts.group(payload.groupId)) 22 | .then(response => response.data) 23 | .then(transformContactsData); 24 | 25 | export default { student, group }; 26 | -------------------------------------------------------------------------------- /test/online-lessons.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import moxios from 'moxios'; 3 | import { endpoints } from '../src/api-config'; 4 | import onlineLessonsController from '../src/controllers/online-lessons'; 5 | import onlineLessonsFixture from './fixtures/online-lessons.json'; 6 | 7 | beforeEach(() => { 8 | moxios.install(); 9 | }); 10 | 11 | afterEach(() => { 12 | moxios.uninstall(); 13 | }); 14 | 15 | test('should return all online lessons', (done) => { 16 | moxios.stubRequest(endpoints.onlineLessons.all, { 17 | status: 200, 18 | response: onlineLessonsFixture.plain, 19 | }); 20 | 21 | onlineLessonsController(axios, { 22 | userId: '0000', 23 | }).then((lessons) => { 24 | expect(lessons).toMatchObject(onlineLessonsFixture.parsed); 25 | done(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/bagrut-grades.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import moxios from 'moxios'; 3 | import { endpoints } from '../src/api-config'; 4 | import bagrutGradesController from '../src/controllers/bagrut-grades'; 5 | import bagrutGradesFixture from './fixtures/bagrut-grades.json'; 6 | 7 | beforeEach(() => { 8 | moxios.install(); 9 | }); 10 | 11 | afterEach(() => { 12 | moxios.uninstall(); 13 | }); 14 | 15 | test('should return all bagrut grades', (done) => { 16 | moxios.stubRequest(endpoints.bagrutGrades('0000'), { 17 | status: 200, 18 | response: bagrutGradesFixture.plain, 19 | }); 20 | 21 | bagrutGradesController(axios, { 22 | userId: '0000', 23 | }).then((bagrutGrades) => { 24 | expect(bagrutGrades).toMatchObject(bagrutGradesFixture.parsed); 25 | done(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/lessons-count.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import moxios from 'moxios'; 3 | import { endpoints } from '../src/api-config'; 4 | import lessonsCountController from '../src/controllers/lessons-count'; 5 | import lessonsCountFixture from './fixtures/lessons-count.json'; 6 | 7 | beforeEach(() => { 8 | moxios.install(); 9 | }); 10 | 11 | afterEach(() => { 12 | moxios.uninstall(); 13 | }); 14 | 15 | test('should return all lessonsCount events', (done) => { 16 | moxios.stubRequest(endpoints.lessonsCount('0000'), { 17 | status: 200, 18 | response: lessonsCountFixture.plain, 19 | }); 20 | 21 | lessonsCountController(axios, { 22 | userId: '0000', 23 | }).then((lessonsCount) => { 24 | expect(lessonsCount).toMatchObject(lessonsCountFixture.parsed); 25 | done(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/fixtures/behave.json: -------------------------------------------------------------------------------- 1 | { 2 | "plain": [{ 3 | "achvaAval": 0, 4 | "achvaCode": 62, 5 | "achvaName": "absense", 6 | "groupId": 1000, 7 | "justification": "approved", 8 | "justificationId": 1, 9 | "lesson": 2, 10 | "lessonId": 1111, 11 | "lessonDate":"2016-09-05T00:00:00", 12 | "lessonReporter": "0000", 13 | "lessonType": 1, 14 | "remark": null, 15 | "reporter": "Teacher1", 16 | "reporterGuid": "0000", 17 | "studentGuid": "2222", 18 | "subject": "Subject1", 19 | "timestamp": "2017-02-26T11:04:17+02:00" 20 | }], 21 | "parsed": [{ 22 | "groupId": 1000, 23 | "lesson": 2, 24 | "date": "2016-09-05T00:00:00", 25 | "type": "absense", 26 | "justification": "approved", 27 | "justificationId": 1, 28 | "reporter": "Teacher1", 29 | "subject": "Subject1" 30 | }] 31 | } 32 | -------------------------------------------------------------------------------- /webpack.config.babel.js: -------------------------------------------------------------------------------- 1 | import webpack from 'webpack'; 2 | import path from 'path'; 3 | 4 | import pkg from './package.json'; 5 | 6 | export default env => ({ 7 | target: 'node', 8 | node: { 9 | process: false, 10 | }, 11 | 12 | entry: './src/index.js', 13 | 14 | mode: env === 'min' ? 'production' : 'none', 15 | 16 | output: { 17 | globalObject: 'this', 18 | filename: env === 'min' ? `${pkg.name}.min.js` : `${pkg.name}.js`, 19 | path: path.resolve(__dirname, 'dist'), 20 | library: 'nodeMashov', 21 | libraryTarget: 'umd', 22 | }, 23 | 24 | module: { 25 | rules: [ 26 | { 27 | test: /\.(js|jsx)$/, 28 | exclude: /node_modules/, 29 | use: 'babel-loader', 30 | }, 31 | ], 32 | }, 33 | 34 | devtool: 'source-maps', 35 | 36 | plugins: [ 37 | new webpack.BannerPlugin({ 38 | banner: `${pkg.name} v${pkg.version} | (c) by ${ 39 | pkg.author.name || pkg.author 40 | }`, 41 | }), 42 | ], 43 | }); 44 | -------------------------------------------------------------------------------- /src/controllers/login.js: -------------------------------------------------------------------------------- 1 | import { extractCookie } from '../utils'; 2 | import { endpoints, apiVersion, appName } from '../api-config'; 3 | 4 | const loginController = (axios, payload) => { 5 | const { school, year, username, password } = payload; 6 | 7 | return axios.post(endpoints.login, { 8 | apiVersion, 9 | appName, 10 | school, 11 | semel: school.id, 12 | year, 13 | username, 14 | password, 15 | }).then((response) => { 16 | const cookies = response.headers['set-cookie'].map(e => extractCookie(e)); 17 | 18 | return { 19 | csrfToken: response.headers['x-csrf-token'] || '', 20 | uniqueId: cookies.find(e => e[0] === 'uniquId')[1], 21 | mashovAuthToken: cookies.find(e => e[0] === 'MashovAuthToken')[1], 22 | correlationId: response.data.credential.correlationId, 23 | sessionId: response.data.credential.correlationId, 24 | userId: response.data.credential.userId, 25 | }; 26 | }); 27 | }; 28 | 29 | export default loginController; 30 | -------------------------------------------------------------------------------- /test/utils.js: -------------------------------------------------------------------------------- 1 | import { extractCookie, createCookieHeader, createQueryString } from '../src/utils'; 2 | 3 | test('extractCookie', () => { 4 | const header = 'cookie1=val1; domain=.place.holder; path=/; secure; httponly'; 5 | const res = extractCookie(header); 6 | 7 | expect(res).toEqual(expect.arrayContaining([ 8 | 'cookie1', 9 | 'val1', 10 | ])); 11 | }); 12 | 13 | test('createCookieHeader', () => { 14 | const cookies = [ 15 | { name: 'cookie1', value: 'val1' }, 16 | { name: 'cookie2', value: 'val2' }, 17 | { name: 'cookie3', value: null }, 18 | ]; 19 | 20 | const res = createCookieHeader(cookies); 21 | 22 | expect(res).toEqual('cookie1=val1; cookie2=val2'); 23 | }); 24 | 25 | test('createQueryString', () => { 26 | const parts = [ 27 | { name: 'par1', value: 'val1' }, 28 | { name: 'par2', value: 'val2' }, 29 | { name: 'par3', value: null }, 30 | ]; 31 | 32 | const res = createQueryString(parts); 33 | 34 | expect(res).toEqual('par1=val1&par2=val2'); 35 | }); 36 | -------------------------------------------------------------------------------- /test/login.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import moxios from 'moxios'; 3 | import { endpoints } from '../src/api-config'; 4 | import loginController from '../src/controllers/login'; 5 | import loginFixture from './fixtures/login.json'; 6 | 7 | beforeEach(() => { 8 | moxios.install(); 9 | }); 10 | 11 | afterEach(() => { 12 | moxios.uninstall(); 13 | }); 14 | 15 | test('should fail if details are wrong', () => { 16 | moxios.stubRequest(endpoints.login, { 17 | status: 401, 18 | }); 19 | 20 | return loginController(axios, { 21 | username: 'username', 22 | password: 'password', 23 | school: {}, 24 | year: 2017, 25 | }).catch((e) => { 26 | expect(e.response.status).toEqual(401); 27 | }); 28 | }); 29 | 30 | test('should resolve if details are correct', () => { 31 | moxios.stubRequest(endpoints.login, { 32 | status: 200, 33 | response: loginFixture.plain, 34 | headers: loginFixture.headers, 35 | }); 36 | 37 | return loginController(axios, { 38 | username: 'username', 39 | password: 'password', 40 | school: {}, 41 | year: 2017, 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Yarden Sod-Moriah 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/contacts.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import moxios from 'moxios'; 3 | import { endpoints } from '../src/api-config'; 4 | import contactsController from '../src/controllers/contacts'; 5 | import contactsFixture from './fixtures/contacts.json'; 6 | 7 | beforeEach(() => { 8 | moxios.install(); 9 | }); 10 | 11 | afterEach(() => { 12 | moxios.uninstall(); 13 | }); 14 | 15 | test('should return all student\'s contacts', (done) => { 16 | moxios.stubRequest(endpoints.contacts.student('0000'), { 17 | status: 200, 18 | response: contactsFixture.plain, 19 | }); 20 | 21 | contactsController.student(axios, { 22 | userId: '0000', 23 | }).then((contacts) => { 24 | expect(contacts).toMatchObject(contactsFixture.parsed); 25 | done(); 26 | }); 27 | }); 28 | 29 | test('should return groups contacts', (done) => { 30 | moxios.stubRequest(endpoints.contacts.group('0000'), { 31 | status: 200, 32 | response: contactsFixture.plain, 33 | }); 34 | 35 | contactsController.group(axios, { 36 | groupId: '0000', 37 | }).then((contacts) => { 38 | expect(contacts).toMatchObject(contactsFixture.parsed); 39 | done(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Extract cookie name & value from header. 3 | * 4 | * 'cookie1=val1; path=/...' ==> ['cookie1', 'val1'] 5 | * 6 | * @param {string} header - The `Cookie` header to parse 7 | * @returns {string[]} 8 | */ 9 | export const extractCookie = header => header.split(';')[0].split('='); 10 | 11 | /** 12 | * Create a simple `Cookie` header. 13 | * 14 | * [{ name: 'c1', value: 'v1' }, { name: 'c2', value: 'v2' }] ==> 'c1=v1; c2=v2' 15 | * 16 | * @param {Object[]} cookies 17 | * @param {string} cookies[].name - Name of the cookie 18 | * @param {string} cookies[].value - Cookie's value 19 | * @returns {string} 20 | */ 21 | export const createCookieHeader = cookies => 22 | cookies.filter(e => e.value).map(e => [e.name, e.value].join('=')).join('; '); 23 | 24 | /** 25 | * Create a query string 26 | * 27 | * [{ name: 'c1', value: 'v1' }, { name: 'c2', value: 'v2' }] ==> 'c1=v1&c2=v2' 28 | * 29 | * @param {Object[]} parts 30 | * @param {string} parts[].name 31 | * @param {string} parts[].value 32 | * @returns {string} 33 | */ 34 | export const createQueryString = parts => 35 | `${parts.filter(e => e.value).map(e => [e.name, e.value].join('=')).join('&')}`; 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-mashov", 3 | "version": "1.1.1", 4 | "description": "A wrapper for Mashov API", 5 | "keywords": [ 6 | "mashov", 7 | "api", 8 | "wrapper", 9 | "school" 10 | ], 11 | "license": "MIT", 12 | "author": { 13 | "name": "Yarden Sod-Moriah", 14 | "email": "yardnsm@gmail.com", 15 | "url": "yardnsm.net" 16 | }, 17 | "files": [ 18 | "dist", 19 | "src", 20 | "src/index.d.ts" 21 | ], 22 | "main": "dist/node-mashov.js", 23 | "module": "src/index.js", 24 | "types": "src/index.d.ts", 25 | "repository": { 26 | "type": "git", 27 | "url": "https://github.com/yardnsm/node-mashov" 28 | }, 29 | "scripts": { 30 | "prebuild": "npm run clean", 31 | "build": "webpack && webpack --env min", 32 | "test": "jest && tsd", 33 | "posttest": "npm run lint", 34 | "lint": "eslint . --ignore-path .gitignore", 35 | "clean": "rm -rf ./dist", 36 | "prepare": "npm run build" 37 | }, 38 | "dependencies": { 39 | "axios": "^0.21.1", 40 | "encodeurl": "^1.0.2" 41 | }, 42 | "devDependencies": { 43 | "@babel/cli": "^7.8.3", 44 | "@babel/core": "^7.8.3", 45 | "@babel/plugin-transform-runtime": "^7.8.3", 46 | "@babel/preset-env": "^7.8.3", 47 | "@babel/register": "^7.8.3", 48 | "@babel/runtime": "^7.8.3", 49 | "babel-eslint": "^10.0.3", 50 | "babel-jest": "^25.1.0", 51 | "babel-loader": "^8.0.6", 52 | "eslint": "^4.18.2", 53 | "eslint-config-airbnb-base": "^11.1.3", 54 | "eslint-plugin-import": "^2.20.0", 55 | "jest": "^25.1.0", 56 | "moxios": "^0.4.0", 57 | "tsd": "^0.14.0", 58 | "webpack": "^4.41.5", 59 | "webpack-cli": "^3.3.10" 60 | }, 61 | "engines": { 62 | "node": ">=4" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/api-config.js: -------------------------------------------------------------------------------- 1 | export const baseUrl = 'https://web.mashov.info/api'; 2 | export const apiVersion = '3.20190301'; 3 | export const appName = 'com.mashov.main'; 4 | 5 | export const endpoints = { 6 | schools: `${baseUrl}/schools`, 7 | login: `${baseUrl}/login`, 8 | logout: `${baseUrl}/logout`, 9 | 10 | conversations: { 11 | inbox: () => `${baseUrl}/mail/inbox/conversations`, 12 | archive: () => `${baseUrl}/mail/archive/conversations`, 13 | unread: () => `${baseUrl}/mail/unread/conversations`, 14 | deleted: () => `${baseUrl}/mail/deleted/conversations`, 15 | sent: () => `${baseUrl}/mail/sent/conversations`, 16 | drafts: () => `${baseUrl}/mail/drafts/conversations`, 17 | search: searchQuery => `${baseUrl}/mail/search/${searchQuery}/conversations`, 18 | single: convId => `${baseUrl}/mail/conversations/${convId}`, 19 | }, 20 | 21 | grades: userId => `${baseUrl}/students/${userId}/grades`, 22 | bagrutGrades: userId => `${baseUrl}/students/${userId}/bagrut/grades`, 23 | behave: userId => `${baseUrl}/students/${userId}/behave`, 24 | lessonsCount: userId => `${baseUrl}/students/${userId}/lessonsCount`, 25 | bells: `${baseUrl}/bells`, 26 | timetable: userId => `${baseUrl}/students/${userId}/timetable`, 27 | 28 | files: { 29 | all: userId => `${baseUrl}/students/${userId}/files`, 30 | single: (userId, fileId, fileName) => `${baseUrl}/students/${userId}/files/${fileId}/${fileName}`, 31 | }, 32 | 33 | groups: userId => `${baseUrl}/students/${userId}/groups`, 34 | 35 | contacts: { 36 | student: userId => `${baseUrl}/students/${userId}/alfon`, 37 | group: groupId => `${baseUrl}/groups/${groupId}/alfon`, 38 | }, 39 | 40 | onlineLessons: { 41 | all: `${baseUrl}/bbb`, 42 | join: lessonId => `${baseUrl}/bbb/join/${lessonId}`, 43 | }, 44 | }; 45 | -------------------------------------------------------------------------------- /test/conversations.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import moxios from 'moxios'; 3 | import { endpoints } from '../src/api-config'; 4 | import conversationsController from '../src/controllers/conversations'; 5 | import fixture from './fixtures/conversations.json'; 6 | 7 | beforeEach(() => { 8 | moxios.install(); 9 | }); 10 | 11 | afterEach(() => { 12 | moxios.uninstall(); 13 | }); 14 | 15 | test('get all conversations', () => { 16 | moxios.stubRequest(endpoints.conversations.inbox('?'), { 17 | status: 200, 18 | response: fixture.all_conversations, 19 | }); 20 | 21 | return conversationsController.all(axios, { 22 | query: 'inbox', 23 | }).then((convs) => { 24 | expect(convs).toMatchObject(fixture.all_conversations_parsed); 25 | }); 26 | }); 27 | 28 | test('generate a query correctly', () => { 29 | const queryExpected = 30 | 'מאת:(sender) אל:(receiver) נושא:(subject) תוכן:(body) יש:(קבצים) מ:(2017-05-01) עד:(2017-05-08)'; 31 | 32 | moxios.stubRequest(endpoints.conversations.search(queryExpected, '?'), { 33 | status: 200, 34 | response: fixture.all_conversations, 35 | }); 36 | 37 | return conversationsController.all(axios, { 38 | query: { 39 | sender: 'sender', 40 | receiver: 'receiver', 41 | subject: 'subject', 42 | body: 'body', 43 | attachment: true, 44 | fromDate: '2017-05-01', 45 | toDate: '2017-05-08', 46 | }, 47 | }); 48 | }); 49 | 50 | test('get a single conversation', () => { 51 | moxios.stubRequest(endpoints.conversations.single('0000'), { 52 | status: 200, 53 | response: fixture.single_conversation, 54 | }); 55 | 56 | return conversationsController.single(axios, { 57 | conversationId: '0000', 58 | }).then((conv) => { 59 | expect(conv).toMatchObject(fixture.single_conversation_parsed); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /test/fixtures/conversations.json: -------------------------------------------------------------------------------- 1 | { 2 | "all_conversations": [{ 3 | "conversationId": "0000", 4 | "subject": "Subject", 5 | "sendTime": "2017-05-01T19:07:11", 6 | "isNew": true, 7 | "hasDrafts": false, 8 | "hasAttachments": true, 9 | "messages": [{ 10 | "messageId": "1111", 11 | "conversationId": "0000", 12 | "senderId": "2222", 13 | "senderName": "Teacher1", 14 | "subject": "Subject", 15 | "lastUpdate": "2017-05-01T19:07:10", 16 | "sendTime": "2017-05-01T19:07:11" 17 | }], 18 | "labels": [] 19 | }], 20 | 21 | "all_conversations_parsed": [{ 22 | "id": "0000", 23 | "subject": "Subject", 24 | "unread": true, 25 | "hasAttachments": true, 26 | "messages": [{ 27 | "id": "1111", 28 | "sender": "Teacher1", 29 | "subject": "Subject", 30 | "timestamp": "2017-05-01T19:07:11" 31 | }] 32 | }], 33 | 34 | "single_conversation": { 35 | "conversationId": "0000", 36 | "subject": "Subject", 37 | "sendTime": "2017-05-01T19:07:11", 38 | "isNew": true, 39 | "hasDrafts": false, 40 | "hasAttachments": true, 41 | "messages":[{ 42 | "messageId": "1111", 43 | "conversationId": "0000", 44 | "senderId": "2222", 45 | "senderName": "Teacher1", 46 | "subject": "Subject", 47 | "body": "

Hello!

", 48 | "lastUpdate": "2017-05-01T19:07:10", 49 | "sendTime": "2017-05-01T19:07:11", 50 | "recipients":[{ 51 | "comment": null, 52 | "displayOrder": 4, 53 | "cssClass": "mshv-contact mshv-contact-teacher", 54 | "value": "y", 55 | "valueType": "ClassCode", 56 | "targetType": "Educators", 57 | "displayName": "All teachers", 58 | "isGroup": true 59 | }], 60 | "cc": null, 61 | "bcc": null, 62 | "folder": 2, 63 | "isNew": true, 64 | "isDeleted": false, 65 | "files": [ 66 | { "fileId": "0000", "fileName": "File1.docx" } 67 | ], 68 | "labels":[], 69 | "smsDetails":null 70 | }], 71 | "labels":[] 72 | }, 73 | 74 | "single_conversation_parsed": { 75 | "id": "0000", 76 | "subject": "Subject", 77 | "unread": true, 78 | "hasAttachments": true, 79 | "messages": [{ 80 | "id": "1111", 81 | "sender": "Teacher1", 82 | "subject": "Subject", 83 | "body": "

Hello!

", 84 | "timestamp": "2017-05-01T19:07:11", 85 | "unread": true, 86 | "deleted": false, 87 | "attachments": [ 88 | { "id": "0000", "name": "File1.docx" } 89 | ] 90 | }] 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/controllers/conversations.js: -------------------------------------------------------------------------------- 1 | import { endpoints } from '../api-config'; 2 | 3 | /** 4 | * Just don't expect to understand this, I 5 | * really don't want to test this. 6 | */ 7 | const createSearchQuery = query => Object.keys(query).map((e) => { 8 | let val = query[e]; 9 | switch (e) { 10 | case 'in': 11 | switch (val) { 12 | case 'inbox': 13 | val = 'דואר נכנס'; 14 | break; 15 | case 'unread': 16 | val = 'דואר שלא נקרא'; 17 | break; 18 | default: 19 | val = 'כל הדואר'; 20 | break; 21 | } 22 | return `ב:(${val})`; 23 | case 'sender': 24 | return `מאת:(${val})`; 25 | case 'receiver': 26 | return `אל:(${val})`; 27 | case 'subject': 28 | return `נושא:(${val})`; 29 | case 'body': 30 | return `תוכן:(${val})`; 31 | case 'attachment': 32 | return 'יש:(קבצים)'; 33 | case 'fromDate': 34 | return `מ:(${val})`; 35 | case 'toDate': 36 | return `עד:(${val})`; 37 | default: 38 | return ''; 39 | } 40 | }).join(' '); 41 | 42 | const all = (axios, payload) => { 43 | const { query, limit, skip } = payload; 44 | 45 | const params = { 46 | take: limit, 47 | skip, 48 | }; 49 | 50 | const endpoint = typeof query === 'string' ? 51 | endpoints.conversations[query]() : 52 | endpoints.conversations.search(createSearchQuery(query)); 53 | 54 | return axios.get(endpoint, { params }) 55 | .then(response => response.data) 56 | .then(data => data.map(e => ({ 57 | id: e.conversationId, 58 | subject: e.subject, 59 | unread: e.isNew, 60 | hasAttachments: e.hasAttachments, 61 | messages: e.messages.map(m => ({ 62 | id: m.messageId, 63 | sender: m.senderName, 64 | subject: m.subject, 65 | timestamp: m.sendTime, 66 | })), 67 | }))); 68 | }; 69 | 70 | const single = (axios, payload) => 71 | axios.get(endpoints.conversations.single(payload.conversationId)) 72 | .then(response => response.data) 73 | .then(data => ({ 74 | id: data.conversationId, 75 | subject: data.subject, 76 | unread: data.isNew, 77 | hasAttachments: data.hasAttachments, 78 | messages: data.messages.map(m => ({ 79 | id: m.messageId, 80 | sender: m.senderName, 81 | subject: m.subject, 82 | body: m.body, 83 | timestamp: m.sendTime, 84 | unread: m.isNew, 85 | deleted: m.isDeleted, 86 | attachments: (m.files || []).map(f => ({ 87 | id: f.fileId, name: f.fileName, 88 | })), 89 | })), 90 | })); 91 | 92 | export default { all, single }; 93 | -------------------------------------------------------------------------------- /src/index.test-d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | import { expectType } from 'tsd'; 4 | import { 5 | fetchSchools, 6 | Client, 7 | 8 | AuthDetails, 9 | 10 | FetchSchoolsResponse, 11 | LoginReponse, 12 | LogoutResponse, 13 | GetConversationsResponse, 14 | GetConversationResponse, 15 | GetGradesResponse, 16 | GetBagrutGradesResponse, 17 | GetBehaveEventsReponse, 18 | GetLessonsCountResponse, 19 | GetBellsReponse, 20 | GetTimetableResponse, 21 | GetFilesResponse, 22 | GetGroupsResponse, 23 | GetContactsResponse, 24 | GetGroupContactsResponse, 25 | GetOnlineLessonsResponse, 26 | } from '.'; 27 | 28 | // Test fetchSchools 29 | expectType(fetchSchools()); 30 | 31 | // Test Client 32 | const client = new Client(); 33 | 34 | expectType(client.getAuthDetails()); 35 | expectType(client.setAuthDetails({ 36 | csrfToken: '0000', 37 | uniquId: '0000', 38 | mashovAuthToken: '0000', 39 | correlationId: '0000', 40 | sessionId: '0000', 41 | userId: '0000', 42 | })); 43 | 44 | expectType(client.setStartDate(null)); 45 | expectType(client.setStartDate('2020-12-31')); 46 | 47 | expectType(client.setEndDate(null)); 48 | expectType(client.setEndDate('2020-12-31')); 49 | 50 | expectType(client.login({ 51 | username: 'username', 52 | password: 'password', 53 | year: 2019, 54 | school: { 55 | id: 1111, 56 | name: 'School', 57 | years: [2019, 2020], 58 | }, 59 | })); 60 | 61 | expectType(client.logout()); 62 | 63 | expectType(client.getConversations('inbox', 20, 0)); 64 | expectType(client.getConversations('archive', 20, 0)); 65 | expectType(client.getConversations('unread', 20, 0)); 66 | expectType(client.getConversations('deleted', 20, 0)); 67 | expectType(client.getConversations('sent', 20, 0)); 68 | expectType(client.getConversations('draft', 20, 0)); 69 | expectType( 70 | client.getConversations({ 71 | in: 'all', 72 | sender: 'Sender', 73 | receiver: 'Receiver', 74 | subject: 'Subject', 75 | attachment: true, 76 | fromDate: '2020-12-31', 77 | }, 20, 0) 78 | ); 79 | expectType( 80 | client.getConversations({ 81 | body: 'Subject', 82 | toDate: '2020-12-31', 83 | }, 20, 0) 84 | ); 85 | 86 | expectType(client.getConversation('0000')); 87 | expectType(client.getGrades()); 88 | expectType(client.getBagrutGrades()); 89 | expectType(client.getBehaveEvents()); 90 | expectType(client.getLessonsCount()); 91 | expectType(client.getBells()); 92 | expectType(client.getTimetable()); 93 | expectType(client.getFiles()); 94 | expectType(client.getGroups()); 95 | expectType(client.getContacts()); 96 | expectType(client.getGroupContacts('0000')); 97 | expectType(client.getOnlineLessons()); 98 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | export interface School { 4 | id: number; 5 | name: string; 6 | years: SchoolYear[]; 7 | } 8 | 9 | export interface AuthDetails { 10 | csrfToken: string; 11 | uniquId: string; 12 | mashovAuthToken: string; 13 | correlationId: string; 14 | sessionId: string; 15 | userId: string; 16 | } 17 | 18 | export interface UserDetails { 19 | username: string; 20 | password: string; 21 | year: SchoolYear; 22 | school: School; 23 | } 24 | 25 | export interface ConversationsComplexQuery { 26 | in?: 'all' | 'inbox' | 'unread'; 27 | sender?: string; 28 | receiver?: string; 29 | subject?: string; 30 | body?: string; 31 | attachment?: boolean; 32 | fromDate?: MashovDate; 33 | toDate?: MashovDate; 34 | } 35 | 36 | export interface Attachment { 37 | id: string; 38 | name: string; 39 | } 40 | 41 | export interface Message { 42 | id: string; 43 | sender: string; 44 | subject: string; 45 | timestamp: string; 46 | body: string; 47 | unread: boolean; 48 | deleted: boolean; 49 | attachments: Attachment[]; 50 | } 51 | 52 | export interface Conversation { 53 | id: string; 54 | subject: string; 55 | unread: boolean; 56 | hasAttachments: boolean; 57 | messages: Message[]; 58 | } 59 | 60 | export interface Grade { 61 | teacher: string; 62 | groupId: MashovGroupId, 63 | subject: string; 64 | date: string; 65 | type: 'exam' | string; // TODO: add more types 66 | event: string; 67 | grade: number; 68 | } 69 | 70 | export interface BagrutGrade { 71 | id: number; 72 | name: string, 73 | yearly: number; 74 | test: number; 75 | final: number; 76 | } 77 | 78 | export interface BehaveEvent { 79 | groupId: MashovGroupId; 80 | lesson: number; 81 | date: string; 82 | type: 'absense' | string; // TODO: add more types 83 | justification: 'approved' | string; // TODO: add more types; 84 | justificationId: number; 85 | reporter: string; 86 | subject: string; 87 | } 88 | 89 | export interface LessonCount { 90 | groupId: MashovGroupId; 91 | lessonCount: number; 92 | weeklyHours: number; 93 | } 94 | 95 | export interface Bell { 96 | lesson: number; 97 | startTime: string; 98 | endTime: string; 99 | } 100 | 101 | export interface TimetableLesson { 102 | groupId: MashovGroupId; 103 | day: number; 104 | lesson: number; 105 | subject: string; 106 | teacher: string; 107 | } 108 | 109 | export interface File { 110 | id: number; 111 | name: string; 112 | groupName: string; 113 | url: string; 114 | } 115 | 116 | export interface Group { 117 | id: MashovGroupId; 118 | name: string; 119 | subject: string; 120 | teacher: string; 121 | } 122 | 123 | export interface Contact { 124 | firstName: string; 125 | lastName: string; 126 | classCode: string; 127 | classNumber: string; 128 | city: string; 129 | address: string; 130 | email: string; 131 | phone: string; 132 | cellphone: string; 133 | } 134 | 135 | export interface OnlineLesson { 136 | lessonId: number; 137 | name: string; 138 | teacher: string; 139 | startTime: string; 140 | endTime: string; 141 | joinLink: string; 142 | } 143 | 144 | export type SchoolYear = number; 145 | export type MashovDate = string | null; 146 | export type MashovGroupId = string; 147 | export type ConversationsQuery = 148 | | 'inbox' 149 | | 'archive' 150 | | 'unread' 151 | | 'deleted' 152 | | 'sent' 153 | | 'draft' 154 | | ConversationsComplexQuery; 155 | 156 | export type FetchSchoolsResponse = Promise; 157 | 158 | export type LoginReponse = Promise; 159 | export type LogoutResponse = Promise; 160 | export type GetConversationsResponse = Promise; 161 | export type GetConversationResponse = Promise; 162 | export type GetGradesResponse = Promise; 163 | export type GetBagrutGradesResponse = Promise; 164 | export type GetBehaveEventsReponse = Promise; 165 | export type GetLessonsCountResponse = Promise; 166 | export type GetBellsReponse = Promise; 167 | export type GetTimetableResponse = Promise; 168 | export type GetFilesResponse = Promise; 169 | export type GetGroupsResponse = Promise; 170 | export type GetContactsResponse = Promise; 171 | export type GetGroupContactsResponse = Promise; 172 | export type GetOnlineLessonsResponse = Promise; 173 | 174 | declare function fetchSchools(): FetchSchoolsResponse; 175 | 176 | export class Client { 177 | getAuthDetails(): AuthDetails; 178 | setAuthDetails(authDetails: AuthDetails): void; 179 | 180 | setStartDate(startDate: MashovDate): Client; 181 | setEndDate(endDate: MashovDate): Client; 182 | 183 | login(userDetails: UserDetails): LoginReponse; 184 | logout(): LogoutResponse; 185 | 186 | getConversations(query: ConversationsQuery, limit: number, skip: number): GetConversationsResponse; 187 | getConversation(conversationId: string): GetConversationResponse; 188 | getGrades(): GetGradesResponse; 189 | getBagrutGrades(): GetBagrutGradesResponse; 190 | getBehaveEvents(): GetBehaveEventsReponse; 191 | getLessonsCount(): GetLessonsCountResponse; 192 | getBells(): GetBellsReponse; 193 | getTimetable(): GetTimetableResponse; 194 | getFiles(): GetFilesResponse; 195 | getGroups(): GetGroupsResponse; 196 | getContacts(): GetContactsResponse; 197 | getGroupContacts(groupId: MashovGroupId): GetGroupContactsResponse; 198 | getOnlineLessons(): GetOnlineLessonsResponse; 199 | } 200 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-mashov 2 | 3 | [![Build Status](https://github.com/yardnsm/node-mashov/workflows/Test/badge.svg)](https://github.com/yardnsm/node-mashov/actions) 4 | [![npm](https://img.shields.io/npm/v/node-mashov)](https://www.npmjs.com/package/node-mashov) 5 | 6 | > A node.js wrapper for [Mashov](http://www.mashov.info/) API. 7 | 8 | Note that: 9 | 10 | - This wrapper focuses on student accounts, so don't expect for parental/teacher accounts support. 11 | - I was too scared to test messages sending, so there isn't such feature here. 12 | - I am not affiliated with Mashov in any way. 13 | 14 | For a full list of features, consult the [API](#api) section. 15 | 16 | ## Install 17 | 18 | Install it from npm: 19 | 20 | ```console 21 | npm install --save node-mashov 22 | ``` 23 | 24 | Or import it in the browser (from `unpkg`, for example): 25 | 26 | ```html 27 | 28 | 29 | 34 | ``` 35 | 36 | ## Usage 37 | 38 | ### Example usage 39 | 40 | ```javascript 41 | import { fetchSchools, Client } from 'node-mashov'; 42 | 43 | (async () => { 44 | const schools = await fetchSchools(); 45 | const school = schools.find(s => s.name.includes('myschool')); 46 | 47 | const client = new Client(); 48 | 49 | client.login({ 50 | username: 'username', 51 | password: 'supersecret', 52 | year: school.years[school.years.length - 1], 53 | school 54 | }).then(client.getGrades) 55 | .then((grades) => { 56 | console.log(grades); 57 | }); 58 | })(); 59 | ``` 60 | 61 | ### API 62 | 63 | > Sample reponses from the API can be found [here](test/fixtures). 64 | 65 | #### fetchSchools() 66 | 67 | Returns a `Promise` for an `Array` of schools. 68 | 69 | #### new Client() 70 | 71 | Create a new client instance. 72 | 73 | #### Client#getAuthDetails() 74 | #### Client#setAuthDetails(authDetails) 75 | 76 | After a successful login, an `authDetails` object is created, containing the required information 77 | for the client to authenticate with the API. You should store those details for future use. 78 | 79 | ##### authDetails 80 | 81 | Type: `Object` 82 | 83 | #### Client#setStartDate(startDate) 84 | #### Client#setEndDate(endDate) 85 | 86 | The API lets you specify time range for records. Those methods allows you to utilize this feture. 87 | 88 | ##### startDate, endDate 89 | 90 | Type: `string`, `null`
91 | Format: `YYYY-MM-DD` 92 | 93 | **All of the following methods return a `Promise`** 94 | 95 | #### Client#login(userDetails) 96 | 97 | Authenticate using the details provided in the constructor. 98 | 99 | ##### userDetails 100 | 101 | Type: `Object` 102 | 103 | ###### username 104 | ###### password 105 | ###### year 106 | ###### school 107 | 108 | #### Client#logout() 109 | 110 | Deauthenticate and destroy authentication details. 111 | 112 | #### Client#getConversations([query], [limit], [skip]) 113 | 114 | Getting the user's conversations. 115 | 116 | ##### query 117 | 118 | Type: `Object`, `string`
119 | Default: `'inbox'` 120 | 121 | Mashov's API lets you query conversations. This wrapper does include support for that. 122 | 123 | If `query` is a `string`, it'll fetch all of the messages matched the type. It could be one of the following: 124 | 125 | - `'inbox'` - Inbox 126 | - `'archive'` - Archived messages 127 | - `'unread'` - Unread messages 128 | - `'deleted'` - Deleted messages 129 | - `'sent'` - Messages sent 130 | - `'draft'` - Drafts 131 | 132 | Otherwise, you can use a more complex query by making `query` into an object, 133 | with the following properties: 134 | 135 | ###### in 136 | 137 | Type: `string`
138 | Default: `'all'` 139 | 140 | - `'all'` - All conversations 141 | - `'inbox'` - Inbox 142 | - `'unread'` - Unread messages 143 | 144 | ###### sender 145 | ###### receiver 146 | ###### subject 147 | ###### body 148 | 149 | Type: `string` 150 | 151 | ###### attachment 152 | 153 | Type: `boolean`
154 | Default: `false` 155 | 156 | If `true`, will query all the conversations that has an attachment. If `false`, it'll query 157 | conversations with or without attachments. 158 | 159 | ###### fromDate 160 | ###### toDate 161 | 162 | Type: `string`
163 | Format: `YYYY-MM-DD` 164 | 165 | > **An example for a valid query:** 166 | > ```javascript 167 | > { 168 | > in: 'unread', 169 | > sender: 'teacher', 170 | > receiver: 'student', 171 | > subject: 'Bring your books tomorrow', 172 | > attachment: true, 173 | > dromDate: '2017-05-01' 174 | > } 175 | > ``` 176 | 177 | ##### limit 178 | 179 | Type: `number`
180 | Default: `20` 181 | 182 | Number of messages to fetch (from start). 183 | 184 | ##### skip 185 | 186 | Type: `number`
187 | Default: `0` 188 | 189 | Number of messages to skip. Can be useful for pagination. 190 | 191 | #### Client#getConversation(conversationId) 192 | 193 | Fetch a single conversation. 194 | 195 | > **Example usage:** 196 | > ```javascript 197 | > client.getAllConversations() 198 | > .then(convs => convs[0].id) 199 | > .then(client.getConversation) 200 | > .then((conv) => { 201 | > console.log(conv); 202 | > }); 203 | > ``` 204 | 205 | #### Client#getGrades() 206 | #### Client#getBagrutGrades() 207 | #### Client#getBehaveEvents() 208 | #### Client#getLessonsCount() 209 | #### Client#getOnlineLessons() 210 | 211 | #### Client#getBells() 212 | 213 | Will fetch the user's school's bell schedule. 214 | 215 | #### Client#getTimetable() 216 | 217 | #### Client#getFiles() 218 | 219 | Will fetch the user's files (aka study materials) 220 | 221 | #### Client#getGroups() 222 | #### Client#getContacts() 223 | 224 | #### Client#getGroupContacts() 225 | 226 | > **Example usage:** 227 | > ```javascript 228 | > client.getGroups() 229 | > .then(groups => groups[0].id) 230 | > .then(client.getGroupContacts) 231 | > .then((contacts) => { 232 | > console.log(contacts); 233 | > }); 234 | > ``` 235 | 236 | --- 237 | 238 | ## See also 239 | 240 | - [mashov-api](https://gitlab.com/yoavst/mashov-api) - Mashov API for JVM platform 241 | 242 | ## License 243 | 244 | MIT © [Yarden Sod-Moriah](http://yardnsm.net/) 245 | -------------------------------------------------------------------------------- /src/client.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import encodeUrl from 'encodeurl'; 3 | import { createCookieHeader, createQueryString } from './utils'; 4 | 5 | import loginController from './controllers/login'; 6 | import logoutController from './controllers/logout'; 7 | 8 | import conversationsController from './controllers/conversations'; 9 | import gradesController from './controllers/grades'; 10 | import bagrutGradesController from './controllers/bagrut-grades'; 11 | import behaveController from './controllers/behave'; 12 | import lessonsCountController from './controllers/lessons-count'; 13 | import bellsController from './controllers/bells'; 14 | import timetableController from './controllers/timetable'; 15 | import filesController from './controllers/files'; 16 | import groupsController from './controllers/groups'; 17 | import contactsController from './controllers/contacts'; 18 | import onlineLessonsController from './controllers/online-lessons'; 19 | 20 | /** 21 | * Mashov API client 22 | */ 23 | class Client { 24 | constructor() { 25 | this._authDetails = null; 26 | this._axiosInstance = null; 27 | 28 | this._startDate = null; 29 | this._endDate = null; 30 | 31 | this._createAxiosInstance = this._createAxiosInstance.bind(this); 32 | this._continueIfAuthenticated = this._continueIfAuthenticated.bind(this); 33 | 34 | this.login = this.login.bind(this); 35 | this.logout = this.logout.bind(this); 36 | 37 | this.getAuthDetails = this.getAuthDetails.bind(this); 38 | this.setAuthDetails = this.setAuthDetails.bind(this); 39 | this.setStartDate = this.setStartDate.bind(this); 40 | this.setEndDate = this.setEndDate.bind(this); 41 | 42 | this.getConversations = this.getConversations.bind(this); 43 | this.getConversation = this.getConversation.bind(this); 44 | this.getGrades = this.getGrades.bind(this); 45 | this.getBagrutGrades = this.getBagrutGrades.bind(this); 46 | this.getBehaveEvents = this.getBehaveEvents.bind(this); 47 | this.getLessonsCount = this.getLessonsCount.bind(this); 48 | this.getBells = this.getBells.bind(this); 49 | this.getTimetable = this.getTimetable.bind(this); 50 | this.getFiles = this.getFiles.bind(this); 51 | this.getGroups = this.getGroups.bind(this); 52 | this.getContacts = this.getContacts.bind(this); 53 | this.getGroupContacts = this.getGroupContacts.bind(this); 54 | this.getOnlineLessons = this.getOnlineLessons.bind(this); 55 | } 56 | 57 | /** 58 | * Create a new Axios instance for the controllers to use. Note that this method does not 59 | * return any value, but rather set `_axiosInstance`. 60 | */ 61 | _createAxiosInstance() { 62 | this._axiosInstance = axios.create({ 63 | headers: { 64 | 'X-Csrf-Token': this._authDetails.csrfToken, 65 | Cookie: createCookieHeader([ 66 | { name: 'uniquId', value: this._authDetails.uniqueId }, 67 | { name: 'MashovAuthToken', value: this._authDetails.mashovAuthToken }, 68 | { name: 'Csrf-Token', value: this._authDetails.csrfToken }, 69 | ]), 70 | }, 71 | paramsSerializer: (params) => { 72 | const parts = Object.keys(params).map(e => ({ name: e, value: params[e] })); 73 | return createQueryString(parts); 74 | }, 75 | }); 76 | 77 | this._axiosInstance.interceptors.request.use((config) => { 78 | const newConfig = config; 79 | 80 | newConfig.url = encodeUrl(config.url); 81 | newConfig.params = Object.assign(newConfig.params || {}, { 82 | start: this._startDate, 83 | end: this._endDate, 84 | }); 85 | 86 | return newConfig; 87 | }); 88 | } 89 | 90 | /** 91 | * Check if we have the user's authDeatils. 92 | * 93 | * @returns {Promise} 94 | */ 95 | _continueIfAuthenticated() { 96 | return new Promise((resolve, reject) => { 97 | if (this._authDetails) { 98 | resolve(); 99 | } else { 100 | reject(new Error('User is not logged in')); 101 | } 102 | }); 103 | } 104 | 105 | /** 106 | * Get the user's authDetails. 107 | * @returns {Object} 108 | */ 109 | getAuthDetails() { 110 | return this._authDetails; 111 | } 112 | 113 | /** 114 | * Set the user's authDetails. 115 | */ 116 | setAuthDetails(authDetails) { 117 | this._authDetails = authDetails; 118 | this._createAxiosInstance(); 119 | } 120 | 121 | /** 122 | * Set start date. 123 | * @returns {Client} 124 | */ 125 | setStartDate(startDate) { 126 | this._startDate = startDate; 127 | return this; 128 | } 129 | 130 | /** 131 | * Set end date. 132 | * @returns {Client} 133 | */ 134 | setEndDate(endDate) { 135 | this._endDate = endDate; 136 | return this; 137 | } 138 | 139 | /** 140 | * Authenticate the API. 141 | * 142 | * @param {Object} userDeatils 143 | * @param {string} userDetails.username 144 | * @param {string} userDetails.password 145 | * @param {number} userDetails.year 146 | * @param {Object} userDetails.school 147 | * @returns {Promise} 148 | */ 149 | login(userDetails) { 150 | return loginController(axios, userDetails).then((authDetails) => { 151 | this._authDetails = authDetails; 152 | }).then(() => { 153 | this._createAxiosInstance(); 154 | }); 155 | } 156 | 157 | /** 158 | * Deauthenticate the API. 159 | * 160 | * @returns {Promise} 161 | */ 162 | logout() { 163 | return logoutController(this._axiosInstance).then(() => { 164 | this._authDetails = null; 165 | this._axiosInstance = null; 166 | }); 167 | } 168 | 169 | /** 170 | * Get the user's conversations. 171 | * 172 | * @returns {Promise} 173 | */ 174 | getConversations(query = 'inbox', limit, skip) { 175 | return this._continueIfAuthenticated().then(() => 176 | conversationsController.all(this._axiosInstance, { 177 | query, 178 | limit, 179 | skip, 180 | })); 181 | } 182 | 183 | /** 184 | * Get a single conversation. 185 | * 186 | * @returns {Promise} 187 | */ 188 | getConversation(conversationId) { 189 | return this._continueIfAuthenticated().then(() => 190 | conversationsController.single(this._axiosInstance, { 191 | conversationId, 192 | })); 193 | } 194 | 195 | /** 196 | * Get the user's grades. 197 | * 198 | * @returns {Promise} 199 | */ 200 | getGrades() { 201 | return this._continueIfAuthenticated().then(() => 202 | gradesController(this._axiosInstance, { 203 | userId: this._authDetails.userId, 204 | })); 205 | } 206 | 207 | /** 208 | * Get the user's Bagrut grades. 209 | * 210 | * @returns {Promise} 211 | */ 212 | getBagrutGrades() { 213 | return this._continueIfAuthenticated().then(() => 214 | bagrutGradesController(this._axiosInstance, { 215 | userId: this._authDetails.userId, 216 | })); 217 | } 218 | 219 | /** 220 | * Get the user's behave events. 221 | * 222 | * @returns {Promise} 223 | */ 224 | getBehaveEvents() { 225 | return this._continueIfAuthenticated().then(() => 226 | behaveController(this._axiosInstance, { 227 | userId: this._authDetails.userId, 228 | })); 229 | } 230 | 231 | /** 232 | * Get the user's lesson count. 233 | * 234 | * @returns {Promise} 235 | */ 236 | getLessonsCount() { 237 | return this._continueIfAuthenticated().then(() => 238 | lessonsCountController(this._axiosInstance, { 239 | userId: this._authDetails.userId, 240 | })); 241 | } 242 | 243 | /** 244 | * Get the user's school's bell schedule. 245 | * 246 | * @returns {Promise} 247 | */ 248 | getBells() { 249 | return this._continueIfAuthenticated().then(() => 250 | bellsController(this._axiosInstance)); 251 | } 252 | 253 | /** 254 | * Get the user's timetable. 255 | * 256 | * @returns {Promise} 257 | */ 258 | getTimetable() { 259 | return this._continueIfAuthenticated().then(() => 260 | timetableController(this._axiosInstance, { 261 | userId: this._authDetails.userId, 262 | })); 263 | } 264 | 265 | /** 266 | * Get the user's study materials. 267 | * 268 | * @returns {Promise} 269 | */ 270 | getFiles() { 271 | return this._continueIfAuthenticated().then(() => 272 | filesController(this._axiosInstance, { 273 | userId: this._authDetails.userId, 274 | })); 275 | } 276 | 277 | /** 278 | * Get the user's groups. 279 | * 280 | * @returns {Promise} 281 | */ 282 | getGroups() { 283 | return this._continueIfAuthenticated().then(() => 284 | groupsController(this._axiosInstance, { 285 | userId: this._authDetails.userId, 286 | })); 287 | } 288 | 289 | /** 290 | * Get the user's contacts. 291 | * 292 | * @returns {Promise} 293 | */ 294 | getContacts() { 295 | return this._continueIfAuthenticated().then(() => 296 | contactsController.student(this._axiosInstance, { 297 | userId: this._authDetails.userId, 298 | })); 299 | } 300 | 301 | /** 302 | * Get the groups's conatcts. 303 | * 304 | * @returns {Promise} 305 | */ 306 | getGroupContacts(groupId) { 307 | return this._continueIfAuthenticated().then(() => 308 | contactsController.group(this._axiosInstance, { 309 | groupId, 310 | })); 311 | } 312 | 313 | /** 314 | * Get the user's online lessons. 315 | * 316 | * @returns {Promise} 317 | */ 318 | getOnlineLessons() { 319 | return this._continueIfAuthenticated().then(() => 320 | onlineLessonsController(this._axiosInstance)); 321 | } 322 | } 323 | 324 | export default Client; 325 | --------------------------------------------------------------------------------