summaryrefslogtreecommitdiff
path: root/ptv.el
blob: 25e0ac24a0cd344fbbf2160d91dd45aac7c60d3e (plain) (blame)
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
;;; ptv.el -- Public Transport Victoria timetable API client -*- lexical-binding: t -*-

;; Copyright (C) 2023 Free Software Foundation.

;; Author: Yuchen Pei <id@ypei.org>
;; Package-Requires: ((emacs "28.2"))

;; This file is part of ptv.el.

;; ptv.el is free software: you can redistribute it and/or modify it under
;; the terms of the GNU Affero General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; ptv.el is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
;; Public License for more details.

;; You should have received a copy of the GNU Affero General Public
;; License along with ptv.el.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; Public Transport Victoria timetable API client.

;;; Code:

(require 'hmac-def)
(require 'hex-util)
;; FIXME: use a library somehow for json fetching.
(require 'my-net)

(defvar ptv-host "https://timetableapi.ptv.vic.gov.au"
  "The PTV Timetable API host.")

(defcustom ptv-dev-key nil "The PTV Timetable API dev key."
  :type '(string)
  :group 'ptv)

(defcustom ptv-dev-id nil "The PTV Timetable API dev id."
  :type '(string)
  :group 'ptv)

(defun ptv-sha1-binary (text)
  "Return the sha-1 digest of TEXT in binary."
  (sha1 text nil nil t))

(define-hmac-function ptv-hmac-sha1-binary ptv-sha1-binary 64 20)

(defun ptv-hmac-sha1 (text key)
  "Return the sha-1 hmac of TEXT using KEY in hex digest."
  (encode-hex-string (ptv-hmac-sha1-binary text key)))

(defun ptv-api-query (path)
  "Format the query url of a query PATH."
  (let* ((path-to-sign
          (format "/v3%s?devid=%s" path ptv-dev-id))
         (sig (upcase (ptv-hmac-sha1 path-to-sign ptv-dev-key))))
    (my-url-fetch-json (format "%s%s&signature=%s" ptv-host path-to-sign sig))))

(defun ptv-api-search (query)
  "Call the search API with QUERY."
  (ptv-api-query (format "/search/%s" (url-hexify-string query))))

(defun ptv-api-departures (route-type stop-id route-id)
  "Call the departures API with ROUTE-TYPE, STOP-ID and ROUTE-ID."
  (ptv-api-query (format "/departures/route_type/%s/stop/%s/route/%s"
                         route-type stop-id route-id)))

(defun ptv-api-directions (route-id)
  "Call the directions API with ROUTE-ID."
  (ptv-api-query (format "/directions/route/%s" route-id)))

(defun ptv-api-runs (route-id)
  "Call the runs API with ROUTE-ID."
  (ptv-api-query (format "/runs/route/%s" route-id)))

(defun ptv-api-pattern (run-ref route-type)
  "Call the patterns API with RUN-REF and ROUTE-TYPE."
  (ptv-api-query (format "/pattern/run/%s/route_type/%s" run-ref route-type)))

(defun ptv-api-stops (lat lon)
  "Call the stops API with LAT(itude) and LON(gitude)."
  (ptv-api-query (format "/stops/location/%s,%s" lat lon)))

(defun ptv-api-disruptions ()
  "Call the disruptions API."
  (ptv-api-query "/disruptions"))

(provide 'ptv)
;;; ptv.el ends here