forked from briandowns/openweathermap
/
weatherweb.go
105 lines (95 loc) · 2.87 KB
/
weatherweb.go
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
// Example of creating a web based application purely using
// the net/http package to display weather information and
// Twitter Bootstrap so it doesn't look like it's '92.
//
// To start the app, run:
// go run weatherweb.go
//
// Accessible via: http://localhost:8888/here
package main
import (
"encoding/json"
"fmt"
"html/template"
owm "github.com/briandowns/openweathermap"
// "io/ioutil"
"net/http"
"os"
)
// URL is a constant that contains where to find the IP locale info
const URL = "http://ip-api.com/json"
// Data will hold the result of the query to get the IP
// address of the caller.
type Data struct {
Status string `json:"status"`
Country string `json:"country"`
CountryCode string `json:"countryCode"`
Region string `json:"region"`
RegionName string `json:"regionName"`
City string `json:"city"`
Zip string `json:"zip"`
Lat float64 `json:"lat"`
Lon float64 `json:"lon"`
Timezone string `json:"timezone"`
ISP string `json:"isp"`
ORG string `json:"org"`
AS string `json:"as"`
Message string `json:"message"`
Query string `json:"query"`
}
// getLocation will get the location details for where this
// application has been run from.
func getLocation() (*Data, error) {
response, err := http.Get(URL)
if err != nil {
return nil, err
}
defer response.Body.Close()
r := &Data{}
if err = json.NewDecoder(response.Body).Decode(&r); err != nil {
return nil, err
}
return r, nil
}
// getCurrent gets the current weather for the provided location in
// the units provided.
func getCurrent(l, u, lang string) (*owm.CurrentWeatherData, error) {
w, err := owm.NewCurrent(u, lang, os.Getenv("OWM_API_KEY")) // Create the instance with the given unit
if err != nil {
return nil, err
}
w.CurrentByName(l) // Get the actual data for the given location
return w, nil
}
// hereHandler will take are of requests coming in for the "/here" route.
func hereHandler(w http.ResponseWriter, r *http.Request) {
location, err := getLocation()
if err != nil {
fmt.Fprint(w, http.StatusInternalServerError)
return
}
wd, err := getCurrent(location.City, "F", "en")
if err != nil {
fmt.Fprint(w, http.StatusInternalServerError)
return
}
// Process our template
t, err := template.ParseFiles("templates/here.html")
if err != nil {
fmt.Fprint(w, http.StatusInternalServerError)
return
}
// We're doin' naughty things below... Ignoring icon file size and possible errors.
_, _ = owm.RetrieveIcon("static/img", wd.Weather[0].Icon+".png")
// Write out the template with the given data
t.Execute(w, wd)
}
// Run the app
func main() {
http.HandleFunc("/here", hereHandler)
// Make sure we can serve our icon files once retrieved
http.HandleFunc("/static/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, r.URL.Path[1:])
})
http.ListenAndServe(":8888", nil)
}