-
Notifications
You must be signed in to change notification settings - Fork 4
/
request.go
180 lines (158 loc) · 5.09 KB
/
request.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
package slider
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"github.com/disintegration/imaging"
"github.com/rs/zerolog/log"
"image"
"image/png"
"io/ioutil"
"net/http"
)
// https://rammb-slider.cira.colostate.edu/
// ?sat=goes-16
// &z=1
// &angle=150
// &im=24
// &ts=1
// &st=0
// &et=0
// &speed=130
// &motion=rock
// &maps%5Bborders%5D=white
// &mops%5Bborders%5D=0.3
// &mhidden%5Bborders%5D=1
// &lat=0&opacity%5B0%5D=1
// &hidden%5B0%5D=0
// &pause=20210404224807
// &slider=-1
// &hide_controls=0
// &mouse_draw=0
// &follow_feature=0
// &follow_hide=0
// &s=rammb-slider
// &sec=full_disk
// &p%5B0%5D=geocolor
// &x=12664.071436031289
// &y=10806.47205375142
// ? - https://rammb-slider.cira.colostate.edu/data/json/goes-16/full_disk/lat/white/latest_times_all.json
// ImageURI is the request address for images. It contains the following fields:
// - Date
// - Satellite
// - Sector
// - Product
// - Image Timestamp
// - Zoom Level
// - Section Y-Position
// - Section X-Position
// Example: https://rammb-slider.cira.colostate.edu/data/imagery/20210404/jpss---northern_hemisphere/cira_geocolor/20210404215820/04/011_007.png
const ImageURI = "https://rammb-slider.cira.colostate.edu/data/imagery/%s/%s---%s/%s/%s/%02d/%03d_%03d.png"
// AvailableDatesURI is the address for retrieving the latest dates for available images.
// - Satellite
// - Sector
// - Product
// Example: https://rammb-slider.cira.colostate.edu/data/json/jpss/northern_hemisphere/cira_geocolor/available_dates.json
const AvailableDatesURI = "https://rammb-slider.cira.colostate.edu/data/json/%s/%s/%s/available_dates.json"
// LatestTimesURI is the address for retrieving the latest times for available images.
// - Satellite
// - Sector
// - Product
// Example: https://rammb-slider.cira.colostate.edu/data/json/jpss/northern_hemisphere/cira_geocolor/latest_times.json
const LatestTimesURI = "https://rammb-slider.cira.colostate.edu/data/json/%s/%s/%s/latest_times.json"
// LatestTimes5760URI is the same as LatestTimesURI but with more times.
const LatestTimes5760URI = "https://rammb-slider.cira.colostate.edu/data/json/%s/%s/%s/latest_times_5760.json"
func AvailableDates(satellite *Satellite, sector *Sector, product *Product) ([]int, error) {
if satellite == nil {
return nil, fmt.Errorf("satellite must not be nil")
}
if sector == nil {
return nil, fmt.Errorf("sector must not be nil")
}
if product == nil {
return nil, fmt.Errorf("product must not be nil")
}
uri := fmt.Sprintf(AvailableDatesURI, satellite.ID, sector.ID, product.Value)
resp, err := http.Get(uri)
if err != nil {
return nil, fmt.Errorf("unable to get available dates: %w", err)
}
defer func() { _ = resp.Body.Close() }()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("unable to read data from HTTP response body: %w", err)
}
data := new(struct {
DatesInt []int `json:"dates_int"`
})
err = json.Unmarshal(body, data)
if err != nil {
return nil, fmt.Errorf("unable to decode available dates JSON: %w", err)
}
return data.DatesInt, nil
}
func LatestTimes(satellite *Satellite, sector *Sector, product *Product, count int) ([]int, error) {
if satellite == nil {
return nil, fmt.Errorf("satellite must not be nil")
}
if sector == nil {
return nil, fmt.Errorf("sector must not be nil")
}
if product == nil {
return nil, fmt.Errorf("product must not be nil")
}
var uri string
if count > 100 {
uri = fmt.Sprintf(LatestTimes5760URI, satellite.ID, sector.ID, product.Value)
} else {
uri = fmt.Sprintf(LatestTimesURI, satellite.ID, sector.ID, product.Value)
}
resp, err := http.Get(uri)
if err != nil {
return nil, fmt.Errorf("unable to get latest times: %w", err)
}
defer func() { _ = resp.Body.Close() }()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("unable to read data from HTTP response body: %w", err)
}
data := new(struct {
TimestampsInt []int `json:"timestamps_int"`
})
err = json.Unmarshal(body, data)
if err != nil {
return nil, fmt.Errorf("unable to decode available dates JSON: %w", err)
}
return data.TimestampsInt, nil
}
type ImageRequest struct {
Date string
Satellite string
Sector string
Product string
ImageTimestamp string
ZoomLevel int
SectionXPosition int
SectionYPosition int
}
func DownloadImage(request *ImageRequest) (image.Image, error) {
uri := fmt.Sprintf(ImageURI, request.Date, request.Satellite, request.Sector, request.Product,
request.ImageTimestamp, request.ZoomLevel, request.SectionYPosition, request.SectionXPosition)
log.Debug().Msgf("Downloading image from: %s", uri)
resp, err := http.Get(uri)
if err != nil {
return nil, fmt.Errorf("unable to get available dates: %w", err)
}
defer func() { _ = resp.Body.Close() }()
img, err := png.Decode(resp.Body)
if err != nil {
return nil, fmt.Errorf("unable to decode image response: %w", err)
}
var gifBytes bytes.Buffer
err = imaging.Encode(bufio.NewWriter(&gifBytes), img, imaging.GIF)
if err != nil {
return nil, fmt.Errorf("unable to encode PNG image as GIF: %w", err)
}
return img, nil
}