You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
3.7 KiB
169 lines
3.7 KiB
package main |
|
|
|
import ( |
|
"bufio" |
|
"bytes" |
|
"fmt" |
|
"io" |
|
"io/ioutil" |
|
"log" |
|
"net/http" |
|
"net/smtp" |
|
"os" |
|
"os/exec" |
|
"path" |
|
"time" |
|
|
|
"github.com/BurntSushi/toml" |
|
homedir "github.com/mitchellh/go-homedir" |
|
"github.com/domodwyer/mailyak" |
|
) |
|
|
|
type Config struct { |
|
MailHost, Username, Password, From string |
|
Recipients []string |
|
MailPort int |
|
Len int64 |
|
} |
|
|
|
var conf Config |
|
var confFile string |
|
|
|
func getConf() Config { |
|
confDir := path.Dir(confFile) |
|
|
|
if _, err := os.Stat(confDir); os.IsNotExist(err) { |
|
log.Printf("Creating config directory") |
|
err = os.MkdirAll(confDir, 0777) |
|
if err != nil { |
|
log.Fatal("Cannot create config directory: ", err) |
|
} |
|
} |
|
if _, err := os.Stat(confFile); os.IsNotExist(err) { |
|
log.Printf("Creating config file") |
|
f, err := os.Create(confFile) |
|
if err != nil { |
|
log.Fatal("Cannot create config file: ", err) |
|
} |
|
err = f.Close() |
|
if err != nil { |
|
log.Fatal("Error closing config file: ", err) |
|
} |
|
} |
|
if _, err := toml.DecodeFile(confFile, &conf); err != nil { |
|
log.Fatal("Error reading config file: ", err) |
|
} |
|
if conf.From == "" { |
|
conf.From = conf.Username + "@" + conf.MailHost |
|
} |
|
of, err := os.Create(path.Join(confDir, "c.R")) |
|
if err != nil { |
|
log.Fatal("Error creating R source file: ", err) |
|
} |
|
_, err = of.WriteString(rCode()) |
|
if err != nil { |
|
log.Fatal("Error writing R source code: ", err) |
|
} |
|
return conf |
|
} |
|
|
|
func save() { |
|
of, err := os.Create(confFile) |
|
if err != nil { |
|
log.Fatal("Cannot open config file: ", err) |
|
} |
|
var buf bytes.Buffer |
|
w := bufio.NewWriter(&buf) |
|
enc := toml.NewEncoder(w) |
|
enc.Encode(conf) |
|
io.Copy(of, &buf) |
|
err = of.Close() |
|
if err != nil { |
|
log.Fatal("Error closing config file: ", err) |
|
} |
|
} |
|
|
|
func fetch() { |
|
url := "https://health.data.ny.gov/api/views/xdss-u53e/rows.csv?accessType=DOWNLOAD" |
|
|
|
resp, err := http.Get(url) |
|
if err != nil { |
|
log.Printf("HTTP error: ", err) |
|
return |
|
} |
|
body, err := ioutil.ReadAll(resp.Body) |
|
if err != nil { |
|
log.Printf("Read error: ", err) |
|
return |
|
} |
|
if int64(len(body)) == conf.Len { |
|
log.Printf("Equal length, returning") |
|
return |
|
} |
|
log.Printf("Length differs: body = %d", len(body)) |
|
conf.Len = int64(len(body)) |
|
save() |
|
|
|
of, err := os.Create(path.Join(path.Dir(confFile), "rows.csv")) |
|
if err != nil { |
|
log.Fatal("Cannot create rows.csv: ", err) |
|
} |
|
_, err = of.Write(body) |
|
if err != nil { |
|
log.Fatal("Error writing rows.csv: ", err) |
|
} |
|
|
|
confDir := path.Dir(confFile) |
|
cmd := exec.Command("R", "--no-save", "-f", path.Join(confDir, "c.R")) |
|
log.Printf("Running R") |
|
err = cmd.Run() |
|
if err != nil { |
|
log.Print("Error running R: ", err) |
|
return |
|
} |
|
log.Printf("R completed") |
|
if conf.MailHost == "" { |
|
log.Print("No mail host set, returning") |
|
return |
|
} |
|
f, err := os.Open("Rplot001.svg") |
|
if err != nil { |
|
log.Fatal("Error opening Rplot001.svg: ", err) |
|
} |
|
defer f.Close() |
|
for _, r := range conf.Recipients { |
|
email := mailyak.New(fmt.Sprintf("%s:%d", conf.MailHost, conf.MailPort), |
|
smtp.PlainAuth("", conf.Username, conf.Password, conf.MailHost)) |
|
email.To(r) |
|
email.From(conf.From) |
|
msg := "Covid dashboard update for " + time.Now().Format("Monday, January 2 2006") |
|
email.Subject(msg) |
|
email.Plain().Set(msg) |
|
email.HTML().Set(`<html><body><img src="dashboard.svg"/></body></html>`) |
|
email.AttachInlineWithMimeType("dashboard.svg", f, "image/svg+xml") |
|
err = email.Send() |
|
if err != nil { |
|
log.Print("Error sending email: ", err) |
|
} else { |
|
log.Print("Sent email to ", r) |
|
} |
|
} |
|
} |
|
|
|
func main() { |
|
log.Printf("starting") |
|
homeDir, err := homedir.Dir() |
|
if err != nil { |
|
log.Fatal("Cannot locate user's home directory") |
|
} |
|
confFile = path.Join(homeDir, ".config", "cget", "cget.conf") |
|
os.Chdir(path.Dir(confFile)) |
|
getConf() |
|
|
|
for { |
|
fetch() |
|
time.Sleep(time.Minute * 30) |
|
} |
|
log.Printf("done") |
|
} |
|
|
|
|