tangled
alpha
login
or
join now
m1emi1em.dev
/
bb-scripts
0
fork
atom
this repo has no description
0
fork
atom
overview
issues
pulls
pipelines
initial commit (broken)
m1emi1em.dev
1 year ago
f0a42831
4e769abb
+91
1 changed file
expand all
collapse all
unified
split
weather
weather.bb
+91
weather/weather.bb
···
1
1
+
#!/usr/bin/env bb
2
2
+
(require '[babashka.http-client :as http]
3
3
+
'[babashka.process :refer [shell process alive?]]
4
4
+
'[clojure.java.io :as io]
5
5
+
'[babashka.fs :as fs])
6
6
+
7
7
+
(def URL "https://api.weather.gov/gridpoints/LWX/88,80/forecast")
8
8
+
9
9
+
(def endpoints {:points "https://api.weather.gov/points/"})
10
10
+
(def pgeocode-cache-path (str (fs/home) "/.cache/pgeocode/US.txt"))
11
11
+
12
12
+
(defn get-all
13
13
+
[coll keyset]
14
14
+
(for [k keyset]
15
15
+
(vector k (get coll k))))
16
16
+
17
17
+
(defn read-csv-to-maps
18
18
+
([] (read-csv-to-maps pgeocode-cache-path))
19
19
+
([fname]
20
20
+
(let [csv-data (-> fname slurp csv/read-csv)]
21
21
+
(map zipmap
22
22
+
(->> (first csv-data)
23
23
+
(map keyword)
24
24
+
repeat)
25
25
+
(rest csv-data)))))
26
26
+
27
27
+
(defn geocode [zipcode]
28
28
+
(first (filter
29
29
+
(fn [{zc :postal_code}] (= zc zipcode))
30
30
+
(read-csv-to-maps))))
31
31
+
32
32
+
(defn api-get
33
33
+
"Make an HTTP GET to url and return the json result"
34
34
+
[url]
35
35
+
(let [response (-> url http/get)]
36
36
+
(if (= (:status response) 500)
37
37
+
(do
38
38
+
(print "Server responded with 500. Rate limit (probably) exceeded. Wait a bit then try again")
39
39
+
(System/exit 1))
40
40
+
(-> response :body json/parse-string))))
41
41
+
42
42
+
(defn form-request
43
43
+
"Forms a request url"
44
44
+
[request-type & args]
45
45
+
(apply str (request-type endpoints) (interpose "," args)))
46
46
+
47
47
+
(defn get-forecast-url
48
48
+
"Gets the endpoint url for the requested latitude and longitude using a points request"
49
49
+
[{latitude :latitude longitude :longitude}]
50
50
+
(-> (form-request :points latitude longitude)
51
51
+
api-get
52
52
+
(get-in ["properties" "forecastHourly"])))
53
53
+
54
54
+
(defn get-forecast [location]
55
55
+
(-> location get-forecast-url api-get
56
56
+
(get-in ["properties" "periods"])
57
57
+
first
58
58
+
(get-all ["temperature" "shortForecast"])))
59
59
+
60
60
+
(defn check-rc []
61
61
+
(let [path (str (fs/home) "/.weatherrc")]
62
62
+
(when (fs/exists? path)
63
63
+
(-> path slurp str/trim-newline))))
64
64
+
65
65
+
(defn display-results
66
66
+
[{city :place_name state :state_code}
67
67
+
[[_ temperature] [_ forecast]]]
68
68
+
(doseq [line [""
69
69
+
(str "The weather in " city ", " state " is:")
70
70
+
(str temperature " F")
71
71
+
(str "Forecast: " forecast)]]
72
72
+
(println line)))
73
73
+
74
74
+
(defn get-weather [postal-code]
75
75
+
(let [location (geocode postal-code)
76
76
+
forecast (get-forecast location)]
77
77
+
(display-results location forecast)))
78
78
+
79
79
+
(defn -main
80
80
+
([]
81
81
+
(if-let [postal-code (check-rc)]
82
82
+
(get-weather postal-code)
83
83
+
(println "No postal code provided")))
84
84
+
85
85
+
([postal-code]
86
86
+
(if (re-matches #"\d{5}" postal-code)
87
87
+
(get-weather postal-code)
88
88
+
(println "Not a valid postal code"))))
89
89
+
90
90
+
(when (= *file* (System/getProperty "babashka.file"))
91
91
+
(apply -main *command-line-args*))