-
Notifications
You must be signed in to change notification settings - Fork 1
/
dataops.go
202 lines (169 loc) · 4.41 KB
/
dataops.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
/*
Mesostic Data Operations
- Filesystem / database access
- Specialized random / hash values
- Configurations
*/
package main
import (
"crypto/sha1"
"fmt"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
"strings"
"time"
"github.com/rs/zerolog/log"
)
// rndDate ::: Produce a random date in the format YYYY-MM-DD.
func rndDate(salt int64) string {
// rand ranges are [0,r)
rMi := 20 // Millinium
rYr := 20 // Years
rMo := 12 // Months
rDy := 31 // Days
rand.Seed(salt)
// No random for millinium
Mi := fmt.Sprint(rMi)
// Yr can be zero
Yr := fmt.Sprintf("%02d", rand.Intn(rYr))
// Don't actually use the last number but then add it back.
Mo := fmt.Sprintf("%02d", rand.Intn(rMo-1)+1)
// Good thing for a test:
// In rare cases this may be > 31,
// but the API should return a 404
// and that will trigger another random selection anyway.
Dy := fmt.Sprintf("%02d", rand.Intn(rDy)+1)
// Formatted YYYY-MM-DD date
newdate := Mi + Yr + "-" + Mo + "-" + Dy
return newdate
}
// envVar ::: Grab a single ENV VAR and provide a fallback configuration.
func envVar(env, alt string) string {
url, ext := os.LookupEnv(env)
if !ext {
url = alt
}
return url
}
// ichingMeso ::: Uses chance operations to select an existing NASA APOD Mesostic.
func ichingMeso(dir string) string {
var fileList []string
for _, entry := range dirents(dir) {
fullPath := filepath.Join(dir, entry.Name())
fmt.Println(fullPath)
fileList = append(fileList, fullPath)
}
if fileList == nil {
log.Error().Msg("ENOENT ::: Is the datastore available?")
return "ENOENT"
}
rand.Seed(time.Now().Unix())
randix := rand.Intn(len(fileList))
return fileList[randix]
}
// dirents ::: read a directory and return its contents
func dirents(d string) []os.FileInfo {
ents, err := ioutil.ReadDir(d)
if err != nil {
log.Error()
return nil
}
return ents
}
// extent ::: file system entry exists
func extent(fs string) bool {
if _, err := os.Stat(fs); err != nil {
return false
}
return true
}
// localDirs ::: set up permanent data directories
func localDirs(ld []string) {
for _, dir := range ld {
if !extent(dir) {
log.Info().Str("directory", dir).Msg("Dir not found, creating.")
err := os.Mkdir(dir, 0700)
if err != nil {
log.Error()
}
}
}
}
// readMesoFile ::: Open and read the Mesostic
func readMesoFile(f *string) string {
if len(*f) == 0 {
log.Error().Msg("no path given")
return "error"
}
var mesoBuf []byte
mesoBuf, err := ioutil.ReadFile(*f)
if err != nil {
log.Error()
}
return string(mesoBuf)
}
// apodNEW ::: Check if a disk file exists in the Mesostic store or create a new one.
// The return values are the filename and whether the function wrote a new file.
func apodNew(sp *string, da *string, me *string) (string, bool) {
_, _, fu := Envelope()
mDir := "store"
tr := strings.NewReplacer(" ", "_")
spn := tr.Replace(*sp)
fP := fmt.Sprintf("%s/%s__%s", mDir, *da, spn)
// NASA API returned a 404
if spn == "404" {
log.Warn().Str("fu", fu).Msg("404 NOFILE")
return fP, false
}
// Mesostic file exists
if _, err := os.Stat(fP); err == nil {
log.Warn().Str("fu", fu).Msg("EXISTENT")
return fP, false
}
// Write data to a new file
sB := []byte(*me)
err := ioutil.WriteFile(fP, sB, 0644)
if err != nil {
log.Error()
}
return fP, true
}
// fileTmp ::: Take a source string and place it in a file name after the spinestring.
// This only creates the file by a straight byte copy.
// Calling functions are responsible for file deletion when finished.
func fileTmp(sp *string, so *string) string {
fT := time.Now()
fS := fT.Unix()
fN := fmt.Sprintf("txrx/%s__%d", *sp, fS)
sB := []byte(*so)
err := ioutil.WriteFile(fN, sB, 0644)
if err != nil {
log.Error()
}
return fN
}
// nasaNewREAD ::: Consume the current filename for the current NASA APOD Mesostic.
// No new data returns the string 'HPSCHD'
func nasaNewREAD() string {
_, _, fu := Envelope()
// The purpose here is to display the current APOD first,
// and random ones subsequently, including the present one.
select {
case mesoFile := <-nasaNewMESO:
log.Info().Str("fu", fu).Msg("Filename from nasaNewMESO consumed")
return mesoFile
default:
log.Info().Str("fu", fu).Msg("No new filename presented, initiate chance operations.")
return "HPSCHD"
}
}
// SHA1 for consistent size keys
func shakey(k string) string {
s := sha1.New()
s.Write([]byte(k))
bash := s.Sum(nil)
hash := fmt.Sprintf("%x", bash)
return hash
}