skolplattformen-backup/libs/api-skolplattformen/devrun.js

240 lines
6.4 KiB
JavaScript

/* eslint-disable @typescript-eslint/no-use-before-define */
/* eslint-disable no-console */
/* eslint-disable import/no-extraneous-dependencies */
/**
* A more elaborated test file for local development
* - Support for proxy (i recommend Burp Suite https://portswigger.net/burp/communitydownload)
* - Saves sessionCoookie to a file and tries to use it again
*/
const { DateTime } = require('luxon')
const { inspect } = require('util')
const nodeFetch = require('node-fetch')
const { CookieJar } = require('tough-cookie')
const fetchCookie = require('fetch-cookie/node-fetch')
// eslint-disable-next-line import/no-unresolved
const { writeFile, readFile } = require('fs/promises')
const path = require('path')
const fs = require('fs')
const HttpProxyAgent = require('https-proxy-agent')
const agentWrapper = require('./agentFetchWrapper')
const init = require('./dist').default
const [, , personalNumber] = process.argv
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
const cookieJar = new CookieJar()
let bankIdUsed = false
async function run() {
const agent = new HttpProxyAgent('http://localhost:8080')
const agentEnabledFetch = agentWrapper(nodeFetch, agent)
const fetch = fetchCookie(agentEnabledFetch, cookieJar)
try {
const api = init(fetch, cookieJar, { record })
api.on('login', async () => {
console.log('Logged in')
if (bankIdUsed) {
const sessionCookie = getSessionCookieFromCookieJar()
ensureDirectoryExistence('./record')
await writeFile(
'./record/latestSessionCookie.txt',
JSON.stringify(sessionCookie)
)
console.log(
'Session cookie saved to file ./record/latesSessionCookie.txt'
)
}
console.log('user')
const user = await api.getUser()
console.log(user)
console.log('children')
const children = await api.getChildren()
console.log(children)
/*
console.log('calendar')
const calendar = await api.getCalendar(children[0])
console.log(calendar)
console.log('classmates')
const classmates = await api.getClassmates(children[0])
console.log(classmates)
*/
try {
console.log('schedule')
const schedule = await api.getSchedule(
children[1],
DateTime.local(),
DateTime.local().plus({ week: 1 })
)
console.log(schedule)
} catch (error) {
console.error(error)
}
let skola24children
try {
skola24children = await api.getSkola24Children()
console.log(skola24children)
} catch (error) {
console.error(error)
}
try {
console.log('timetable')
const timetable = await api.getTimetable(
skola24children[0],
15,
2021,
'sv'
)
console.log(inspect(timetable, false, 1000, true))
} catch (error) {
console.error(error)
}
/*
console.log('news')
const news = await api.getNews(children[0])
*/
/* console.log('news details')
const newsItems = await Promise.all(
news.map((newsItem) =>
api.getNewsDetails(children[0], newsItem)
.catch((err) => { console.error(newsItem.id, err) })
)
)
console.log(newsItems) */
/* console.log('menu')
const menu = await api.getMenu(children[0])
console.log(menu) */
// console.log('notifications')
// const notifications = await api.getNotifications(children[0])
// console.log(notifications)
await api.logout()
})
api.on('logout', () => {
console.log('Logged out')
process.exit(0)
})
// Eventhandlers above must be setup before calling login
bankIdUsed = await Login(api)
} catch (err) {
console.error(err)
}
}
async function Login(api) {
let useBankId = true
try {
console.log('Attempt to use saved session cookie to login')
const rawContent = await readFile('./record/latestSessionCookie.txt')
const sessionCookie = JSON.parse(rawContent)
await api.setSessionCookie(`${sessionCookie.key}=${sessionCookie.value}`)
useBankId = false
console.log('Login with old cookie succeeded')
} catch (error) {
console.log('Could not login with old session cookie. Reverting to BankId')
// console.error(error)
}
if (useBankId) {
console.log('*** BankId login - open BankId app ***')
if (!personalNumber) {
console.error(
'You must pass in a valid personal number, eg `node run 197001011111`'
)
process.exit(1)
}
const status = await api.login(personalNumber)
status.on('PENDING', () => console.log('PENDING'))
status.on('USER_SIGN', () => console.log('USER_SIGN'))
status.on('ERROR', () => console.error('ERROR'))
status.on('OK', () => console.log('OK'))
status.on('CANCELLED', () => {
console.log('User cancelled login')
process.exit(0)
})
}
return useBankId
}
function ensureDirectoryExistence(filePath) {
const dirname = path.dirname(filePath)
if (fs.existsSync(dirname)) {
return
}
ensureDirectoryExistence(dirname)
fs.mkdirSync(dirname)
}
function getSessionCookieFromCookieJar() {
const cookies = cookieJar.getCookiesSync('https://etjanst.stockholm.se')
const sessionCookie = cookies.find((c) => c.key === 'SMSESSION')
return sessionCookie
}
const record = async (info, data) => {
const name = info.error ? `${info.name}_error` : info.name
const filename = `./record/${name}.json`
ensureDirectoryExistence(filename)
const content = {
url: info.url,
headers: info.headers,
status: info.status,
statusText: info.statusText,
}
if (data) {
switch (info.type) {
case 'json':
content.json = data
break
case 'text':
content.text = data
break
case 'blob': {
const buffer = await data.arrayBuffer()
content.blob = Buffer.from(buffer).toString('base64')
break
}
default:
throw new Error('Unknown data type')
}
} else if (info.error) {
const { message, stack } = info.error
content.error = {
message,
stack,
}
}
await writeFile(filename, JSON.stringify(content, null, 2))
}
// Hack to keep it running while wating for await
const timer = setTimeout(() => {
// noop
}, 999999)
run()
.then(() => {
clearTimeout(timer)
console.log('...')
})
.catch((err) => {
clearTimeout(timer)
console.error(err)
})