import std/[asyncdispatch, asynchttpserver] import std/[parseutils, strutils] import std/[times, math] import std/[json, options] import threadvars, types, utils, fedi proc saveState(state: JsonNode) = var json_encoded: string toUgly(json_encoded, state) writeFile(storagePath & "/state.json", json_encoded) proc requestHandler* (req: Request) {.async.} = echo $req.reqMethod & " " & $req.url.path & " " & req.headers.getOrDefault("user-agent") & ": " & req.body let headers = {"Content-type": "text/plain; charset=utf-8"} if config.ServerAccessToken.isSome: if not req.headers.hasKey("Authorization"): await req.respond(Http401, "Wrong access-token provided.", headers.newHttpHeaders()) return else: if req.headers.getOrDefault("Authorization") != "Bearer " & config.ServerAccessToken.get: await req.respond(Http401, "Wrong access-token provided.", headers.newHttpHeaders()) return try: let entityBodyJson = parseJson(req.body) var reason = entityBodyJson["reason"].getStr if reason == "checkout": reason = "update" case reason: of "ping": state = newJObject() saveState(state) var response = "[fedi-create-post] error: Unkown error happend!" let post = await fediPost(config, "This is a test post from travelynx2fedi!", PostDirect) if post["responseCode"].getStr != "200 OK": response = "[fedi-create-post] error: " & post["error"].getStr else: response = "[fedi-create-post] created post " & $post["id"] & ": " & $post["content"] await req.respond(Http200, response, headers.newHttpHeaders()) return of "checkin": state = newJObject() saveState(state) await req.respond(Http200, "[checkin] recieved checkin!", headers.newHttpHeaders()) return of "update": var statusUrl: string var statusText: string var statusVisibility: PostVisibility = PostDirect var response: string var responseCode: HttpCode = Http200 if state.hasKey("checkin_id") and state.hasKey("to_station"): if ( state["checkin_id"].getStr == entityBodyJson["status"]["fromStation"]["scheduledTime"].getStr and state["to_station"].getStr == entityBodyJson["status"]["toStation"]["name"].getStr and state["comment"].getStr == entityBodyJson["status"]["comment"].getStr and state["visibilityLevel"].getInt == entityBodyJson["status"]["visibility"]["level"].getInt ): await req.respond(Http200, "[checkin] Already posted!" & response, headers.newHttpHeaders()) return if ( state.hasKey("post_id") and ( state["to_station"].getStr != entityBodyJson["status"]["toStation"]["name"].getStr or state["comment"].getStr != entityBodyJson["status"]["comment"].getStr ) ): let post = await fediDelete(config, state["post_id"].getStr) if post["responseCode"].getStr != "200 OK": responseCode = Http500 response = "[fedi-delete-post] error: " & post["error"].getStr await req.respond(responseCode, "[checkin] " & response, headers.newHttpHeaders()) return else: state = newJObject() saveState(state) response = "[fedi-delete-post] successfully deleted post " & $post["id"] if config.TravelynxUsername.isSome: let token = $entityBodyJson["status"]["fromStation"]["uic"] & "-" & $floorMod( entityBodyJson["status"]["actionTime"].getInt , 337 ) statusUrl = "http://travelynx.de/status/" & config.TravelynxUsername.get & "/" & $entityBodyJson["status"]["fromStation"]["scheduledTime"] & "?token=" & token let vehicle = entityBodyJson["status"]["train"]["type"].getStr & " " & entityBodyJson["status"]["train"]["no"].getStr if config.FediUseMarkdown: statusText = "Ich bin gerade in [" & vehicle & " nach " & entityBodyJson["status"]["toStation"]["name"].getStr & "](" & statusUrl & ")" else: statusText = "Ich bin gerade in " & vehicle & " nach " & entityBodyJson["status"]["toStation"]["name"].getStr & " " & statusUrl if entityBodyJson["status"]{"comment"}.getStr != "": if config.FediUseMarkdown: statusText = entityBodyJson["status"]["comment"].getStr & " ([" & vehicle & " → " & entityBodyJson["status"]["toStation"]["name"].getStr & "](" & statusUrl & "))" else: statusText = entityBodyJson["status"]["comment"].getStr & " (" & vehicle & " → " & entityBodyJson["status"]["toStation"]["name"].getStr & " " & statusUrl & ")" if config.FediVisibility.isSome: if (entityBodyJson["status"]["visibility"]["level"].getInt <= 10): statusVisibility = PostDirect else: statusVisibility = config.FediVisibility.get else: if (entityBodyJson["status"]["visibility"]["level"].getInt <= 30): statusVisibility = PostDirect if (entityBodyJson["status"]["visibility"]["level"].getInt <= 60): statusVisibility = PostPrivate if (entityBodyJson["status"]["visibility"]["level"].getInt == 100): statusVisibility = PostUnlisted let post = await fediPost(config, statusText, statusVisibility) if post["responseCode"].getStr != "200 OK": response = "[fedi-create-post] error: " & post["error"].getStr else: state["checkin_id"] = entityBodyJson["status"]["fromStation"]["scheduledTime"] state["to_station"] = entityBodyJson["status"]["toStation"]["name"] state["post_id"] = post["id"] state["post_time"] = newJInt(toUnix(getTime())) state["comment"] = entityBodyJson["status"]["comment"] state["visibilityLevel"] = entityBodyJson["status"]["visibility"]["level"] saveState(state) response = "[fedi-create-post] created post " & $post["id"] & ": " & $post["content"] await req.respond(responseCode, "[checkin] " & response, headers.newHttpHeaders()) of "undo": var response: string var responseCode: HttpCode = Http200 if state.hasKey("post_id") and state.hasKey("post_time"): let currentTime = toUnix(getTime()) if currentTime - state["post_time"].getInt < 15*60: let post = await fediDelete(config, state["post_id"].getStr) if post["responseCode"].getStr != "200 OK": responseCode = Http500 response = "[fedi-delete-post] error: " & post["error"].getStr else: state = newJObject() saveState(state) response = "[fedi-delete-post] successfully deleted post " & $post["id"] else: response = "Post too old!" else: response = "Nothing posted yet!" await req.respond(responseCode, "[undo] " & response, headers.newHttpHeaders()) else: await req.respond(Http400, "Invalid request", headers.newHttpHeaders()) return except: let e = getCurrentException() msg = getCurrentExceptionMsg() echo "Got exception ", repr(e), " with message ", msg await req.respond(Http500, "Internal server error, whoops", headers.newHttpHeaders()) return