forked from briandowns/openweathermap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
openweathermap.go
238 lines (208 loc) · 6.2 KB
/
openweathermap.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
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
// Copyright 2015 Brian J. Downs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package openweathermap
import (
"errors"
"log"
"net/http"
)
var errUnitUnavailable = errors.New("unit unavailable")
var errLangUnavailable = errors.New("language unavailable")
var errInvalidKey = errors.New("invalid api key")
var errInvalidOption = errors.New("invalid option")
var errInvalidHttpClient = errors.New("invalid http client")
// DataUnits represents the character chosen to represent the temperature notation
var DataUnits = map[string]string{"C": "metric", "F": "imperial", "K": "internal"}
var (
baseURL = "http://api.openweathermap.org/data/2.5/weather?%s"
iconURL = "http://openweathermap.org/img/w/%s"
stationURL = "http://api.openweathermap.org/data/2.5/station?id=%d"
forecastBase = "http://api.openweathermap.org/data/2.5/forecast/daily?appid=%s&%s&mode=json&units=%s&lang=%s&cnt=%d"
historyURL = "http://api.openweathermap.org/data/2.5/history/%s"
pollutionURL = "http://api.openweathermap.org/pollution/v1/co/"
uvURL = "http://api.openweathermap.org/data/2.5/"
dataPostURL = "http://openweathermap.org/data/post"
)
// LangCodes holds all supported languages to be used
// inspried and sourced from @bambocher (github.com/bambocher)
var LangCodes = map[string]string{
"EN": "English",
"RU": "Russian",
"IT": "Italian",
"ES": "Spanish",
"SP": "Spanish",
"UK": "Ukrainian",
"UA": "Ukrainian",
"DE": "German",
"PT": "Portuguese",
"RO": "Romanian",
"PL": "Polish",
"FI": "Finnish",
"NL": "Dutch",
"FR": "French",
"BG": "Bulgarian",
"SV": "Swedish",
"SE": "Swedish",
"TR": "Turkish",
"HR": "Croatian",
"CA": "Catalan",
"ZH_TW": "Chinese Traditional",
"ZH": "Chinese Simplified",
"ZH_CN": "Chinese Simplified",
}
// Config will hold default settings to be passed into the
// "NewCurrent, NewForecast, etc}" functions.
type Config struct {
Mode string // user choice of JSON or XML
Unit string // measurement for results to be displayed. F, C, or K
Lang string // should reference a key in the LangCodes map
APIKey string // API Key for connecting to the OWM
Username string // Username for posting data
Password string // Pasword for posting data
}
// APIError returned on failed API calls.
type APIError struct {
Message string `json:"message"`
COD string `json:"cod"`
}
// Coordinates struct holds longitude and latitude data in returned
// JSON or as parameter data for requests using longitude and latitude.
type Coordinates struct {
Longitude float64 `json:"lon"`
Latitude float64 `json:"lat"`
}
// Sys struct contains general information about the request
// and the surrounding area for where the request was made.
type Sys struct {
Type int `json:"type"`
ID int `json:"id"`
Message float64 `json:"message"`
Country string `json:"country"`
Sunrise int `json:"sunrise"`
Sunset int `json:"sunset"`
}
// Wind struct contains the speed and degree of the wind.
type Wind struct {
Speed float64 `json:"speed"`
Deg float64 `json:"deg"`
}
// Weather struct holds high-level, basic info on the returned
// data.
type Weather struct {
ID int `json:"id"`
Main string `json:"main"`
Description string `json:"description"`
Icon string `json:"icon"`
}
// Main struct contains the temperates, humidity, pressure for the request.
type Main struct {
Temp float64 `json:"temp"`
TempMin float64 `json:"temp_min"`
TempMax float64 `json:"temp_max"`
Pressure float64 `json:"pressure"`
SeaLevel float64 `json:"sea_level"`
GrndLevel float64 `json:"grnd_level"`
Humidity int `json:"humidity"`
}
// Clouds struct holds data regarding cloud cover.
type Clouds struct {
All int `json:"all"`
}
// func getKey() string {
// key := os.Getenv("OWM_API_KEY")
// if !ValidAPIKey(key) {
// log.Fatalln(errInvalidKey)
// }
// return key
// }
func setKey(key string) string {
if !ValidAPIKey(key) {
log.Fatalln(errInvalidKey)
}
return key
}
// ValidDataUnit makes sure the string passed in is an accepted
// unit of measure to be used for the return data.
func ValidDataUnit(u string) bool {
for d := range DataUnits {
if u == d {
return true
}
}
return false
}
// ValidLangCode makes sure the string passed in is an
// acceptable lang code.
func ValidLangCode(c string) bool {
for d := range LangCodes {
if c == d {
return true
}
}
return false
}
// ValidDataUnitSymbol makes sure the string passed in is an
// acceptable data unit symbol.
func ValidDataUnitSymbol(u string) bool {
for _, d := range DataUnits {
if u == d {
return true
}
}
return false
}
// ValidAPIKey makes sure that the key given is a valid one
func ValidAPIKey(key string) bool {
if len(key) == 32 {
return true
}
return false
}
// CheckAPIKeyExists will see if an API key has been set.
func (c *Config) CheckAPIKeyExists() bool { return len(c.APIKey) > 1 }
// Settings holds the client settings
type Settings struct {
client *http.Client
}
// NewSettings returns a new Setting pointer with default http client.
func NewSettings() *Settings {
return &Settings{
client: http.DefaultClient,
}
}
// Optional client settings
type Option func(s *Settings) error
// WithHttpClient sets custom http client when creating a new Client.
func WithHttpClient(c *http.Client) Option {
return func(s *Settings) error {
if c == nil {
return errInvalidHttpClient
}
s.client = c
return nil
}
}
// setOptions sets Optional client settings to the Settings pointer
func setOptions(settings *Settings, options []Option) error {
for _, option := range options {
if option == nil {
return errInvalidOption
}
err := option(settings)
if err != nil {
return err
}
}
return nil
}