bk/bakalari.nim

170 lines
5.3 KiB
Nim

import httpcore, httpclient, json, strformat, tables, times, uri
import elvis
type
Bakalari* = ref object
website*: Uri
accessToken*: string
refreshToken*: string
Homework* = object
id*: string
subject*: string
teacher*: string
content*: string
startTime*: DateTime
endTime*: DateTime
Message* = object
title*: string
sender*: string
text*: string
sentTime*: DateTime
Hour* = ref object
number*: string
beginTime*: string
endTime*: string
Room* = ref object
name*: string
abbrev*: string
Subject* = ref object
name*: string
abbrev*: string
Teacher* = ref object
name*: string
abbrev*: string
Lesson* = object
hour*: Hour
room*: Room
subject*: Subject
teacher*: Teacher
Day* = object
lessons*: seq[Lesson]
dayOfWeek*: int
date*: DateTime
Timetable* = object
days*: seq[Day]
const
iso8601 = initTimeFormat("yyyy-MM-dd'T'HH:mm:sszzz")
proc newBakalari*(website: Uri, username: string, password: string): Bakalari =
new result
result.website = website
let
api = website / "api/login"
client = newHttpClient()
response = client.post($api, body = &"client_id=ANDR&grant_type=password&username={username}&password={password}")
root = response.body.parseJson
result.accessToken = root{"access_token"}.getStr
result.refreshToken = root{"refresh_token"}.getStr
proc newBakalari*(website: Uri, refreshToken: string): Bakalari =
new result
result.website = website
let
api = website / "api/login"
client = newHttpClient()
response = client.post($api, body = &"client_id=ANDR&grant_type=refresh_token&refresh_token={refreshToken}")
root = response.body.parseJson
result.accessToken = root{"access_token"}.getStr
result.refreshToken = root{"refresh_token"}.getStr
func accessToken*(bakalari: Bakalari): string =
bakalari.accessToken
func refreshToken*(bakalari: Bakalari): string =
bakalari.refreshToken
proc renewTokens(bakalari: Bakalari) =
let
api = bakalari.website / "api/login"
client = newHttpClient()
response = client.post($api, body = &"client_id=ANDR&grant_type=refresh_token&refresh_token={bakalari.refreshToken}")
body = response.body
root = body.parseJson
bakalari.accessToken = root{"access_token"}.getStr
bakalari.refreshToken = root{"refresh_token"}.getStr
proc getEndpoint*(bakalari: Bakalari, endpoint: string): JsonNode =
let
api = bakalari.website / "api/3" / endpoint
client = newHttpClient(headers = newHttpHeaders {
"Authorization": "Bearer " & bakalari.accessToken,
})
response = client.get($api)
body = response.body
bakalari.renewTokens
result = body.parseJson
proc postEndpoint*(bakalari: Bakalari, endpoint: string): JsonNode =
let
api = bakalari.website / "api/3" / endpoint
client = newHttpClient(headers = newHttpHeaders {
"Authorization": "Bearer " & bakalari.accessToken,
})
response = client.post($api)
body = response.body
bakalari.renewTokens
result = body.parseJson
iterator homework*(bakalari: Bakalari): Homework =
let root = bakalari.getEndpoint("homeworks")
for node in root{"Homeworks"}.getElems:
yield Homework(
id: node{"ID"}.getStr,
subject: node{"Subject"}{"Name"}.getStr,
teacher: node{"Teacher"}.getStr,
content: node{"Content"}.getStr,
startTime: node{"DateStart"}.getStr.parse(iso8601),
endTime: node{"DateEnd"}.getStr.parse(iso8601),
)
iterator messages*(bakalari: Bakalari): Message =
let root = bakalari.postEndpoint("komens/messages/received")
for node in root{"Messages"}.getElems:
yield Message(
title: node{"Title"}.getStr,
sender: node{"Sender"}{"Name"}.getStr,
text: node{"Text"}.getStr,
sentTime: node{"SentDate"}.getStr.parse(iso8601)
)
proc timetable*(bakalari: Bakalari, permanent: bool): Timetable =
let root = bakalari.getEndpoint(permanent ? "timetable/permanent" ! "timetable/actual")
var hours: Table[int, Hour]
for hourNode in root{"Hours"}:
hours[hourNode{"Id"}.getInt] = Hour(
number: hourNode{"Caption"}.getStr,
beginTime: hourNode{"BeginTime"}.getStr,
endTime: hourNode{"EndTime"}.getStr,
)
var rooms: Table[string, Room]
for roomNode in root{"Rooms"}:
rooms[roomNode{"Id"}.getStr] = Room(
name: roomNode{"Name"}.getStr,
abbrev: roomNode{"Abbrev"}.getStr,
)
var subjects: Table[string, Subject]
for subjectNode in root{"Subjects"}:
subjects[subjectNode{"Id"}.getStr] = Subject(
name: subjectNode{"Name"}.getStr,
abbrev: subjectNode{"Abbrev"}.getStr,
)
var teachers: Table[string, Teacher]
for teacherNode in root{"Teachers"}:
teachers[teacherNode{"Id"}.getStr] = Teacher(
name: teacherNode{"Name"}.getStr,
abbrev: teacherNode{"Abbrev"}.getStr,
)
for dayNode in root{"Days"}:
var day: Day
for lessonNode in dayNode{"Atoms"}:
var lesson: Lesson
lesson.hour = hours[lessonNode{"HourId"}.getInt]
lesson.subject = subjects[lessonNode{"SubjectId"}.getStr]
lesson.teacher = teachers[lessonNode{"TeacherId"}.getStr]
lesson.room = rooms[lessonNode{"RoomId"}.getStr]
day.lessons.add lesson
day.dayOfWeek = dayNode{"DayOfWeek"}.getInt
day.date = dayNode{"Date"}.getStr.parse(iso8601)
result.days.add day