122 lines
4.9 KiB
Nim
122 lines
4.9 KiB
Nim
import json, logging, os, strformat, times, uri
|
|
import bakalari, users
|
|
|
|
when not defined(release):
|
|
let consoleLogger = newConsoleLogger()
|
|
consoleLogger.addHandler
|
|
|
|
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):
|
|
fatal "User configuration diractory not found, quitting"
|
|
quit QuitFailure
|
|
for userConfigFile in walkFiles(userConfigDir / "*.json"):
|
|
let userName = userConfigFile.extractFilename.changeFileExt("")
|
|
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
|
|
of "bakalari_message_forwarding":
|
|
userConfig.services.add(Service(kind: srvBakalariMessageForwarding))
|
|
of "bakalari_mark_forwarding":
|
|
userConfig.services.add(Service(kind: srvBakalariMarkForwarding))
|
|
of "bakalari_daily_timetable":
|
|
userConfig.services.add(Service(kind: srvBakalariDailyTimetable))
|
|
else:
|
|
warn &"Unknown service kind: \"{kindStr}\""
|
|
yield User(name: userName, config: userConfig, data: UserData(lastServeTime: 0.fromUnix.utc))
|
|
|
|
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}"
|
|
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:
|
|
user.serve(userCredentialsDir, userDataDir)
|
|
except:
|
|
error &"An exception was raised while processing user:\n {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace}"
|