jlelse
/
kis3
Archived
1
Fork 0

Add daily reports feature

This commit is contained in:
Jan-Lukas Else 2019-05-01 10:56:39 +02:00
parent 88d5a33084
commit 8813185419
5 changed files with 94 additions and 15 deletions

View File

@ -3,18 +3,29 @@ package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"os"
"strconv"
)
type config struct {
Port string `json:"port"`
Dnt bool `json:"dnt"`
DbPath string `json:"dbPath"`
StatsUsername string `json:"statsUsername"`
StatsPassword string `json:"statsPassword"`
Port string `json:"port"`
Dnt bool `json:"dnt"`
DbPath string `json:"dbPath"`
StatsUsername string `json:"statsUsername"`
StatsPassword string `json:"statsPassword"`
Reports []report `json:"reports"`
}
type report struct {
Name string `json:"name"`
Time string `json:"time"`
To string `json:"to"`
SmtpUser string `json:"smtpUser"`
SmtpPassword string `json:"smtpPassword"`
SmtpHost string `json:"smtpHost"`
From string `json:"from"`
Query string `json:"query"`
}
var (
@ -31,7 +42,6 @@ func init() {
parseConfigFile(appConfig)
// Replace values that are set via environment vars (to make it compatible with old method)
overwriteEnvVarValues(appConfig)
fmt.Println(appConfig)
}
func parseConfigFile(appConfig *config) {

3
go.mod
View File

@ -6,12 +6,15 @@ require (
github.com/go-sql-driver/mysql v1.4.1 // indirect
github.com/gobuffalo/packr v1.25.0 // indirect
github.com/gobuffalo/packr/v2 v2.2.0
github.com/google/uuid v1.1.1 // indirect
github.com/gorilla/handlers v1.4.0
github.com/gorilla/mux v1.7.1
github.com/jordan-wright/email v0.0.0-20190218024454-3ea4d25e7cf8
github.com/lib/pq v1.1.0 // indirect
github.com/mattn/go-sqlite3 v0.0.0-20190424093727-5994cc52dfa8
github.com/mssola/user_agent v0.5.0
github.com/rubenv/sql-migrate v0.0.0-20190327083759-54bad0a9b051
github.com/whiteshtef/clockwork v0.0.0-20190417075149-ecf7d9abe8ec
github.com/ziutek/mymysql v1.5.4 // indirect
google.golang.org/appengine v1.5.0 // indirect
gopkg.in/gorp.v1 v1.7.2 // indirect

6
go.sum
View File

@ -24,10 +24,14 @@ github.com/gobuffalo/packr/v2 v2.2.0 h1:Ir9W9XIm9j7bhhkKE9cokvtTl1vBm62A/fene/ZC
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/handlers v1.4.0/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jordan-wright/email v0.0.0-20190218024454-3ea4d25e7cf8 h1:XMe1IsRiRx3E3M50BhP7327VYF4A9RpCFfhHUFW+IeE=
github.com/jordan-wright/email v0.0.0-20190218024454-3ea4d25e7cf8/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@ -55,6 +59,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/whiteshtef/clockwork v0.0.0-20190417075149-ecf7d9abe8ec h1:4mCJZnO75zjolpdsj/ToKe7X1oLWm+JJHwS1ez8BkXY=
github.com/whiteshtef/clockwork v0.0.0-20190417075149-ecf7d9abe8ec/go.mod h1:6o8H8sci2q3QxZ4p/U88ggqZuhY3mg34+WE5BuazLsU=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

18
main.go
View File

@ -21,7 +21,9 @@ type kis3 struct {
}
var (
app = &kis3{}
app = &kis3{
staticBox: packr.New("staticFiles", "./static"),
}
)
func init() {
@ -30,7 +32,7 @@ func init() {
log.Fatal("Database setup failed:", e)
}
setupRouter()
app.staticBox = packr.New("staticFiles", "./static")
setupReports()
}
func main() {
@ -49,13 +51,13 @@ func setupRouter() {
viewRouter := app.router.PathPrefix("/view").Subrouter()
viewRouter.Use(corsHandler)
viewRouter.Path("").HandlerFunc(trackView)
viewRouter.Path("").HandlerFunc(TrackingHandler)
app.router.HandleFunc("/stats", requestStats)
app.router.HandleFunc("/stats", StatsHandler)
staticRouter := app.router.PathPrefix("").Subrouter()
staticRouter.Use(corsHandler)
staticRouter.HandleFunc("/kis3.js", serveTrackingScript)
staticRouter.HandleFunc("/kis3.js", TrackingScriptHandler)
staticRouter.PathPrefix("").Handler(http.HandlerFunc(HelloResponseHandler))
}
@ -66,7 +68,7 @@ func startListening() {
log.Fatal(http.ListenAndServe(addr, app.router))
}
func trackView(w http.ResponseWriter, r *http.Request) {
func TrackingHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate, max-age=0")
url := r.URL.Query().Get("url")
ref := r.URL.Query().Get("ref")
@ -81,7 +83,7 @@ func HelloResponseHandler(w http.ResponseWriter, _ *http.Request) {
_, _ = fmt.Fprint(w, "Hello from KISSS")
}
func serveTrackingScript(w http.ResponseWriter, r *http.Request) {
func TrackingScriptHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/javascript")
w.Header().Set("Cache-Control", "public, max-age=432000") // 5 days
filename := "kis3.js"
@ -97,7 +99,7 @@ func serveTrackingScript(w http.ResponseWriter, r *http.Request) {
http.ServeContent(w, r, filename, stat.ModTime(), file)
}
func requestStats(w http.ResponseWriter, r *http.Request) {
func StatsHandler(w http.ResponseWriter, r *http.Request) {
// Require authentication
if appConfig.statsAuth() {
if !helpers.CheckAuth(w, r, appConfig.StatsUsername, appConfig.StatsPassword) {

58
reports.go Normal file
View File

@ -0,0 +1,58 @@
package main
import (
"fmt"
"github.com/jordan-wright/email"
"github.com/whiteshtef/clockwork"
"io/ioutil"
"net"
"net/http"
"net/smtp"
)
func setupReports() {
scheduler := clockwork.NewScheduler()
for _, r := range appConfig.Reports {
scheduler.Schedule().Every().Day().At(r.Time).Do(func() {
executeReport(&r)
})
}
go scheduler.Run()
}
func executeReport(r *report) {
fmt.Println("Execute report:", r.Name)
req, e := http.NewRequest("GET", "http://localhost:"+appConfig.Port+"/stats?"+r.Query, nil)
if e != nil {
fmt.Println("Executing report failed:", e)
return
}
req.SetBasicAuth(appConfig.StatsUsername, appConfig.StatsPassword)
res, e := http.DefaultClient.Do(req)
if e != nil {
fmt.Println("Executing report failed:", e)
return
}
body, e := ioutil.ReadAll(res.Body)
if e != nil {
fmt.Println("Executing report failed:", e)
return
}
sendMail(r, body)
}
func sendMail(r *report, content []byte) {
smtpHostNoPort, _, _ := net.SplitHostPort(r.SmtpHost)
mail := email.NewEmail()
mail.From = r.From
mail.To = []string{r.To}
mail.Subject = "KISSS report: " + r.Name
mail.Text = content
e := mail.Send(r.SmtpHost, smtp.PlainAuth("", r.SmtpUser, r.SmtpPassword, smtpHostNoPort))
if e != nil {
fmt.Println("Sending report failed:", e)
return
} else {
fmt.Println("Report sent")
}
}