Semi-working signin and timetable
This commit is contained in:
commit
64745479c6
|
@ -0,0 +1,7 @@
|
||||||
|
*
|
||||||
|
!*.*
|
||||||
|
!/**/
|
||||||
|
*.swp
|
||||||
|
*.un~
|
||||||
|
.netrwhist
|
||||||
|
*.json
|
|
@ -0,0 +1,169 @@
|
||||||
|
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
|
|
@ -0,0 +1,62 @@
|
||||||
|
import json, os, times, unicode, uri
|
||||||
|
import cligen
|
||||||
|
import bakalari
|
||||||
|
|
||||||
|
type
|
||||||
|
Config = object
|
||||||
|
website: string
|
||||||
|
username: string
|
||||||
|
refreshToken: string
|
||||||
|
|
||||||
|
const
|
||||||
|
defaultConfigFile = getConfigDir() / "bk.json"
|
||||||
|
|
||||||
|
proc loadConfig(configFile = defaultConfigFile): Config =
|
||||||
|
defaultConfigFile.readFile.parseJson.to(Config)
|
||||||
|
|
||||||
|
proc saveConfig(configFile = defaultConfigFile, config: Config) =
|
||||||
|
configFile.writeFile((%*config).pretty)
|
||||||
|
|
||||||
|
proc signin(
|
||||||
|
website: string,
|
||||||
|
username: string,
|
||||||
|
password: string,
|
||||||
|
configFile = defaultConfigFile,
|
||||||
|
) =
|
||||||
|
let
|
||||||
|
bakalari = newBakalari(website.parseUri, username, password)
|
||||||
|
config = Config(
|
||||||
|
website: website,
|
||||||
|
username: username,
|
||||||
|
refreshToken: bakalari.refreshToken,
|
||||||
|
)
|
||||||
|
configFile.saveConfig(config)
|
||||||
|
|
||||||
|
proc rozvrh(
|
||||||
|
configFile = defaultConfigFile,
|
||||||
|
date = "",
|
||||||
|
oneDay = false,
|
||||||
|
permanent = false,
|
||||||
|
) =
|
||||||
|
var config = configFile.loadConfig
|
||||||
|
let bakalari = newBakalari(config.website.parseUri, config.refreshToken)
|
||||||
|
config.refreshToken = bakalari.refreshToken
|
||||||
|
configFile.saveConfig(config)
|
||||||
|
let timetable = bakalari.timetable(permanent)
|
||||||
|
for day in timetable.days:
|
||||||
|
stdout.writeLine day.date.format("yyyyMMdd")
|
||||||
|
for lesson in day.lessons:
|
||||||
|
var line = ""
|
||||||
|
line &= lesson.hour.number
|
||||||
|
line &= ". "
|
||||||
|
line &= lesson.hour.beginTime.align(5, '0'.Rune)
|
||||||
|
line &= "-"
|
||||||
|
line &= lesson.hour.endTime.align(5, '0'.Rune)
|
||||||
|
line &= " "
|
||||||
|
line &= lesson.subject.abbrev.align(4)
|
||||||
|
line &= " "
|
||||||
|
line &= lesson.teacher.abbrev.align(4)
|
||||||
|
line &= " "
|
||||||
|
line &= lesson.room.abbrev.align(4)
|
||||||
|
stdout.writeLine line
|
||||||
|
dispatchMulti([signin], [rozvrh])
|
Loading…
Reference in New Issue