package main import ( "context" "errors" "fmt" "io" "os" "os/signal" "go.opentelemetry.io/otel" ) const name = "go.sour.is/xt" var ( tracer = otel.Tracer(name) meter = otel.Meter(name) ) type contextKey struct{ name string } type console struct { io.Reader io.Writer err io.Writer context.Context abort func() } func (c console) Log(v ...any) { fmt.Fprintln(c.err, v...) } func (c console) Args() args { v, ok := c.Get("args").(args) if !ok { return args{} } return v } func (c *console) Set(name string, value any) { c.Context = context.WithValue(c.Context, contextKey{name}, value) } func (c console) Get(name string) any { return c.Context.Value(contextKey{name}) } type args struct { dbtype string dbfile string baseFeed string Nick string URI string Listen string } func env(key, def string) string { if v, ok := os.LookupEnv(key); ok { return v } return def } func main() { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) console := console{os.Stdin, os.Stdout, os.Stderr, ctx, stop} go func() { <-ctx.Done(); console.Log("shutdown"); stop() }() args := args{ dbtype: env("XT_DBTYPE", "sqlite3"), dbfile: env("XT_DBFILE", "file:twt.db"), baseFeed: env("XT_BASE_FEED", "feed"), Nick: env("XT_NICK", "xuu"), URI: env("XT_URI", "https://txt.sour.is/users/xuu/twtxt.txt"), Listen: env("XT_LISTEN", ":8040"), } console.Set("args", args) if err := run(console); err != nil && !errors.Is(err, context.Canceled) { fmt.Println(err) os.Exit(1) } }