summaryrefslogtreecommitdiff
path: root/src/bahnhofname.gleam
blob: 232f0f7667e93c9cf8d8a74e42d7457728720529 (plain)
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
import gleam/http/response.{Response}
import gleam/http/request.{Request}
import gleam/http.{Get}
import gleam/bit_builder.{BitBuilder}
import gleam/erlang/process
import gleam/io
import gleam/string
import gleam/list
import gleam/map.{Map}
import gleam/result.{lazy_unwrap}
import gleam/uri
import gleam/hackney
import mist

fn the_lookup(
  query: String,
  stations: Map(String, String),
  ds100s: Map(String, String),
) -> String {
  map.get(ds100s, query)
  |> lazy_unwrap(fn() {
    io.println(query)
    map.get(stations, query)
    |> lazy_unwrap(fn() { "unknown" })
  })
}

fn lookup_station(
  request: Request(t),
  stations: Map(String, String),
  ds100s: Map(String, String),
  baseurl: String,
) -> Response(BitBuilder) {
  let #(code, text) = case request {
    Request(method: Get, path: "/help", ..) -> #(
      200,
      "ds100 → Name: " <> baseurl <> "/FF\n" <> "Name → ds100: " <> baseurl <> "/Frankfurt Hbf",
    )
    Request(method: Get, path: "/" <> path, ..) -> #(
      200,
      the_lookup(string.replace(path, each: "%20", with: " "), stations, ds100s),
    )
    _ -> #(404, "intended usage is e.g. curl " <> baseurl <> "/FF")
  }
  let body = bit_builder.from_string(text)

  response.new(code)
  |> response.prepend_header(
    "x-data-source",
    "https://data.deutschebahn.com/dataset/data-betriebsstellen.html",
  )
  |> response.set_body(body)
}

fn fetch_data() -> Result(String, hackney.Error) {
  let assert Ok(uri) =
    uri.parse(
      "https://download-data.deutschebahn.com/static/datasets/betriebsstellen/DBNetz-Betriebsstellenverzeichnis-Stand2021-10.csv",
    )
  let assert Ok(request) = request.from_uri(uri)
  let assert Ok(response) = hackney.send(request)

  Ok(response.body)
}

fn read_csv() -> List(#(String, String)) {
  // let assert Ok(contents) = file.read(path)
  let assert Ok(contents) = fetch_data()
  contents
  // the file doesn't use quotes, so this is fine
  |> string.split(on: "\n")
  |> list.map(fn(a) { string.split(a, on: ";") })
  |> list.filter_map(fn(fields) {
    case fields {
      [_, ds100, name, ..] -> Ok(#(name, ds100))
      _ -> Error(fields)
    }
  })
}

pub fn main() {
  let baseurl = "https://bahnhof.name"
  let stations = read_csv()
  let stationmap =
    stations
    |> map.from_list
  let ds100map =
    stations
    |> list.map(fn(a) { #(a.1, a.0) })
    |> map.from_list

  let assert Ok(_) = mist.run_service(
    1234,
    fn(req) { lookup_station(req, stationmap, ds100map, baseurl) },
    max_body_limit: 100,
  )
  process.sleep_forever()
}