twitchalitics/main.go

114 lines
2.4 KiB
Go

package main
import (
"context"
"database/sql"
"database/sql/driver"
"embed"
"flag"
"log"
"net/http"
"os"
"github.com/tailscale/sqlite"
"tailscale.com/tsnet"
"tailscale.com/types/logger"
"within.website/ln"
"within.website/ln/ex"
)
const (
twitchDateFormat = `Mon Jan 02 2006` // Fri Dec 17 2021
sqliteDateFormat = "2006-01-02" // 2006-02-01
)
var (
dbLoc = flag.String("db", "var/twitchalitics.db", "path to SQLite database file")
hostname = flag.String("hostname", "twitchalitics", "hostname to use on your tailnet")
tsLogLoc = flag.String("ts-log-loc", "/mnt/fast/share/twitchalitics.ts.log", "path for Tailscale to dump logs")
//go:embed schema/*
schemaFS embed.FS
)
func getDB() (*sql.DB, error) {
connInitFunc := func(ctx context.Context, conn driver.ConnPrepareContext) error {
err := sqlite.ExecScript(conn.(sqlite.SQLConn), "PRAGMA journal_mode=WAL;")
if err != nil {
return err
}
schema, err := schemaFS.ReadFile("schema/schema.sql")
if err != nil {
return err
}
return sqlite.ExecScript(conn.(sqlite.SQLConn), string(schema))
}
db := sql.OpenDB(sqlite.Connector(*dbLoc, connInitFunc, nil))
err := db.Ping()
if err != nil {
return nil, err
}
return db, nil
}
func getLogFout(fname string) (func(), logger.Logf, error) {
os.Remove(fname)
fout, err := os.Create(fname)
if err != nil {
return nil, nil, err
}
done := func() { fout.Close() }
lgr := log.New(fout, "", log.LstdFlags)
return done, lgr.Printf, nil
}
func main() {
os.Setenv("TAILSCALE_USE_WIP_CODE", "true")
flag.Parse()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
db, err := getDB()
if err != nil {
ln.FatalErr(ctx, err)
}
defer db.Close()
ln.Log(ctx, ln.Info("starting up..."), ln.F{"db": *dbLoc, "hostname": hostname, "ts-log-loc": *tsLogLoc})
done, tsLgr, err := getLogFout(*tsLogLoc)
if err != nil {
ln.FatalErr(ctx, err)
}
defer done()
srv := &tsnet.Server{
Hostname: *hostname,
Logf: tsLgr,
}
_ = srv
go plainHTTPRedirect(ctx, srv)
ln.FatalErr(ctx, NewServer(db, srv).ListenAndServe())
}
func plainHTTPRedirect(ctx context.Context, srv *tsnet.Server) {
l, err := srv.Listen("tcp", ":80")
if err != nil {
ln.FatalErr(ctx, err)
}
ln.Log(ctx, ln.Info("listening on :80 to forward to HTTPS"))
err = http.Serve(l, ex.HTTPLog(http.RedirectHandler("https://twitchalitics.shark-harmonic.ts.net", http.StatusPermanentRedirect)))
ln.FatalErr(ctx, err)
}