1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
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