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) }