blob: e38c285f7380190609869a578c92640cd34a74f9 (
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
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
|
;;; delivery-track.el --- Track packages -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2024 Óscar Nájera
;;
;; Author: Óscar Nájera <hi@oscarnajera.com>
;; Maintainer: Óscar Nájera <hi@oscarnajera.com>
;; Created: August 28, 2024
;; Modified: August 28, 2024
;; Version: 0.0.1
;; Keywords: abbrev bib c calendar comm convenience data docs emulations extensions faces files frames games hardware help hypermedia i18n internal languages lisp local maint mail matching mouse multimedia news outlines processes terminals tex tools unix vc wp
;; Homepage: https://github.com/titan/delivery-track
;; Package-Requires: ((emacs "29.1"))
;;
;; This file is not part of GNU Emacs.
;;
;;; Commentary:
;;
;; Track packages
;;
;;; Code:
(require 'org)
(require 'org-id)
(require 'url)
(defvar url-http-end-of-headers)
(defun delivery-track-write-time! (timestring)
"Insert an org inactive timestamp from a parse-able TIMESTRING."
(thread-first
timestring
(parse-time-string)
(encode-time)
(org-insert-timestamp t t)))
(defun delivery-track-org-entry (buffer shipment-id status events)
"Write update on BUFFER the SHIPMENT-ID with STATUS and EVENTS."
(with-current-buffer buffer
(goto-char (org-find-entry-with-id shipment-id))
(org-entry-put nil "status" status)
(org-next-visible-heading 1)
(seq-let (level _rlevel _todo _prio headline)
(org-heading-components)
(when (and (= level 2)
(string= "Shipment reverse history" headline))
(org-cut-subtree))
(insert "** Shipment reverse history\n")
(seq-doseq (event events)
(seq-let (time status) event
(delivery-track-write-time! time)
(insert " " status "\n"))))))
(defun delivery-track--process-response (_request-status buffer provider-parser)
"Process API response with PROVIDER-PARSER and update into BUFFER."
(goto-char url-http-end-of-headers)
(apply #'delivery-track-org-entry
buffer
(funcall provider-parser (json-parse-buffer))))
(defun delivery-track-entry--dhl (response)
"Parse DHL RESPONSE into standard delivery-track info for writer."
(let* ((shipment-info (seq-find
(lambda (item)
(eq t (gethash "hasCompleteDetails" item)))
(gethash "sendungen" response)))
(history (thread-last
shipment-info
(gethash "sendungsdetails")
(gethash "sendungsverlauf"))))
(list
(gethash "id" shipment-info)
(gethash "kurzStatus" history)
(thread-last
(gethash "events" history)
(seq-keep (lambda (event)
(when-let ((time (gethash "datum" event)))
(list time (gethash "status" event)))))
(reverse)))))
(defun delivery-track-entry--hermes (response)
"Parse hermes RESPONSE into standard delivery-track info for writer."
(list
(gethash "barcode" response)
(thread-last response (gethash "status") (gethash "parcelStatus"))
(thread-last
(gethash "parcelHistory" response)
(seq-keep (lambda (event)
(when-let ((time (gethash "timestamp" event)))
(list time (gethash "statusHistoryText" event)))))
(reverse))))
(defun delivery-track--dhl-de (track-id)
"Async request to dhl API using TRACK-ID.
Write update on the org-node in current buffer."
(let* ((url-request-method "GET")
(params `((piececode ,track-id)
("noRedirect" true)
(language "en"))))
(thread-first
"https://www.dhl.de/int-verfolgen/data/search?"
(concat (url-build-query-string params))
(url-retrieve #'delivery-track--process-response
(list (current-buffer) #'delivery-track-entry--dhl)))))
(defun delivery-track--hermes-de (track-id)
"Async request to hermes API using TRACK-ID.
Write update on the org-node in current buffer."
(let* ((url-request-method "GET")
(url-request-extra-headers
'(("User-Agent" . "Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0"))))
(thread-first
"https://api.my-deliveries.de/tnt/parcelservice/parceldetails/"
(concat track-id)
(url-retrieve #'delivery-track--process-response
(list (current-buffer) #'delivery-track-entry--hermes)))))
(defun delivery-track-update (track-id provider)
"Update tracking information for TRACK-ID under PROVIDER.
Interactive defaults to current buffer's org-node id and provider properties."
(interactive (list (read-string "What is the tracking id? " (org-id-get))
(completing-read "Which service provider? "
'(dhl hermes) nil t (org-entry-get nil "provider"))))
(pcase provider
("dhl" (delivery-track--dhl-de track-id ))
("hermes" (delivery-track--hermes-de track-id))))
(provide 'delivery-track)
;;; delivery-track.el ends here
|