More functionality
This commit is contained in:
parent
d810c8a32e
commit
9d688f5303
44
bakalari.nim
44
bakalari.nim
|
@ -1,22 +1,22 @@
|
|||
import httpcore, httpclient, json, strformat, times, uri
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
const
|
||||
iso8601 = initTimeFormat("yyyy-MM-dd'T'HH:mm:sszzz")
|
||||
|
@ -33,6 +33,18 @@ proc newBakalari*(website: Uri, username: string, password: string): Bakalari =
|
|||
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}")
|
||||
body = response.body
|
||||
root = body.parseJson
|
||||
result.accessToken = root{"access_token"}.getStr
|
||||
result.refreshToken = root{"refresh_token"}.getStr
|
||||
|
||||
func accessToken*(bakalari: Bakalari): string =
|
||||
bakalari.accessToken
|
||||
|
||||
|
|
92
dva.nim
92
dva.nim
|
@ -1,13 +1,18 @@
|
|||
import json, logging, os, strformat
|
||||
import json, logging, os, strformat, times, uri
|
||||
import bakalari, users
|
||||
|
||||
when not defined(release):
|
||||
let consoleLogger = newConsoleLogger()
|
||||
consoleLogger.addHandler
|
||||
|
||||
let
|
||||
const
|
||||
iso8601 = initTimeFormat("yyyy-MM-dd'T'HH:mm:sszzz")
|
||||
|
||||
let
|
||||
configDir = getConfigDir() / "dva"
|
||||
userConfigDir = configDir / "userconfig"
|
||||
userCredentialsDir = configDir / "usercredentials"
|
||||
userDataDir = configDir / "userdata"
|
||||
|
||||
iterator usersFromUserConfigDir*(userConfigDir: string): User =
|
||||
if not existsDir(userConfigDir):
|
||||
|
@ -18,6 +23,7 @@ iterator usersFromUserConfigDir*(userConfigDir: string): User =
|
|||
info &"Loading configuration of user {userName}"
|
||||
let userConfigNode = userConfigFile.readFile.parseJson
|
||||
var userConfig: UserConfig
|
||||
userConfig.email = userConfigNode{"email"}.getStr
|
||||
for serviceNode in userConfigNode{"services"}:
|
||||
let kindStr = serviceNode{"kind"}.getStr
|
||||
case kindStr
|
||||
|
@ -29,15 +35,87 @@ iterator usersFromUserConfigDir*(userConfigDir: string): User =
|
|||
userConfig.services.add(Service(kind: srvBakalariDailyTimetable))
|
||||
else:
|
||||
warn &"Unknown service kind: \"{kindStr}\""
|
||||
yield User(name: userName, config: userConfig)
|
||||
yield User(name: userName, config: userConfig, data: UserData(lastServeTime: 0.fromUnix.utc))
|
||||
|
||||
proc serveUser*(user: User) =
|
||||
proc loadCredentials(user: User, userCredentialsDir: string) =
|
||||
info &"Loading credentials of user {user.name}"
|
||||
let userCredentialsFile = userCredentialsDir / user.name.addFileExt("json")
|
||||
if existsFile(userCredentialsFile):
|
||||
let userCredentialsNode = userCredentialsFile.readFile.parseJson
|
||||
let bakalariNode = userCredentialsNode{"bakalari"}
|
||||
block bakalari:
|
||||
if bakalariNode != nil:
|
||||
if "website" notin bakalariNode or "refresh_token" notin bakalariNode:
|
||||
error "Bakaláři credentials don't include website and refresh token"
|
||||
break bakalari
|
||||
user.bakalari = newBakalari(
|
||||
bakalariNode{"website"}.getStr.parseUri,
|
||||
bakalariNode{"refresh_token"}.getStr,
|
||||
)
|
||||
|
||||
proc storeCredentials(user: User, userCredentialsDir: string) =
|
||||
info &"Storing credentials of user {user.name}"
|
||||
let userCredentialsFile = userCredentialsDir / user.name.addFileExt("json")
|
||||
let userCredentialsNode = newJObject()
|
||||
block bakalari:
|
||||
if user.bakalari != nil:
|
||||
userCredentialsNode{"bakalari"} = %*{
|
||||
"website": $user.bakalari.website,
|
||||
"refresh_token": user.bakalari.refreshToken,
|
||||
}
|
||||
userCredentialsFile.writeFile userCredentialsNode.pretty
|
||||
|
||||
proc loadData(user: User, userDataDir: string) =
|
||||
info &"Loading data of user {user.name}"
|
||||
let userDataFile = userDataDir / user.name.addFileExt("json")
|
||||
if existsFile(userDataFile):
|
||||
let userDataNode = userDataFile.readFile.parseJson
|
||||
user.data.lastServeTime = userDataNode{"last_serve_time"}.getStr.parse(iso8601)
|
||||
|
||||
proc storeData(user: User, userDataDir: string) =
|
||||
info &"Storing data of user {user.name}"
|
||||
let userDataFile = userDataDir / user.name.addFileExt("json")
|
||||
let userDataNode = %*{
|
||||
"last_serve_time": user.data.lastServeTime.format(iso8601)
|
||||
}
|
||||
userDataFile.writeFile userDataNode.pretty
|
||||
|
||||
proc serve*(user: User, userCredentialsDir: string, userDataDir: string) =
|
||||
user.loadCredentials(userCredentialsDir)
|
||||
user.loadData(userDataDir)
|
||||
info &"Serving user {user.name}"
|
||||
discard
|
||||
let serveTime = now()
|
||||
for service in user.config.services:
|
||||
case service.kind
|
||||
of srvBakalariMessageForwarding:
|
||||
if user.bakalari == nil:
|
||||
error "Bakaláři message forwarding service is enabled, but user is not logged in to Bakaláři"
|
||||
continue
|
||||
for message in user.bakalari.messages:
|
||||
if message.sentTime >= user.data.lastServeTime:
|
||||
debug "Sending a message"
|
||||
else: discard
|
||||
user.data.lastServeTime = serveTime
|
||||
user.storeData(userDataDir)
|
||||
|
||||
when isMainModule:
|
||||
if "--login-bakalari" in commandLineParams():
|
||||
stdout.write "User: "
|
||||
let userName = stdin.readLine
|
||||
for user in usersFromUserConfigDir(userConfigDir):
|
||||
if user.name == userName:
|
||||
user.loadCredentials(userCredentialsDir)
|
||||
stdout.write "Bakalari website: "
|
||||
let bakalariWebsite = stdin.readLine.parseUri
|
||||
stdout.write "Bakalari username: "
|
||||
let bakalariUsername = stdin.readLine
|
||||
stdout.write "Bakalari password: "
|
||||
let bakalariPassword = stdin.readLine
|
||||
user.bakalari = newBakalari(bakalariWebsite, bakalariUsername, bakalariPassword)
|
||||
user.storeCredentials(userCredentialsDir)
|
||||
break
|
||||
for user in usersFromUserConfigDir(userConfigDir):
|
||||
try:
|
||||
serveUser user
|
||||
user.serve(userCredentialsDir, userDataDir)
|
||||
except:
|
||||
error &"An exception was raised while serving user:\n {getCurrentExceptionMsg()}"
|
||||
error &"An exception was raised while processing user:\n {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace}"
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import times
|
||||
import bakalari
|
||||
|
||||
type
|
||||
ServiceKind* = enum
|
||||
srvBakalariMessageForwarding
|
||||
|
@ -12,7 +15,12 @@ type
|
|||
of srvBakalariDailyTimetable:
|
||||
discard
|
||||
UserConfig* = object
|
||||
email*: string
|
||||
services*: seq[Service]
|
||||
UserData* = object
|
||||
lastServeTime*: DateTime
|
||||
User* = ref object
|
||||
name*: string
|
||||
config*: UserConfig
|
||||
data*: UserData
|
||||
bakalari*: Bakalari
|
||||
|
|
Loading…
Reference in New Issue