mlisting

Mailing list service

git clone git://git.lin.moe/go/mlisting.git

  1package config
  2
  3import (
  4	"context"
  5	"log/slog"
  6	"net/url"
  7	"os"
  8	"path"
  9	"time"
 10
 11	"github.com/BurntSushi/toml"
 12)
 13
 14type Config struct {
 15	Log struct {
 16		Level string `toml:"level"`
 17	} `toml:"log"`
 18
 19	Http struct {
 20		Home          string `toml:"home"`
 21		Listen        string `toml:"listen"`
 22		IndexPage     string `toml:"index-page"`
 23		MetricsListen string `toml:"metrics-listen"`
 24	} `toml:"http"`
 25
 26	LMTP struct {
 27		Listen      string        `toml:"listen"`
 28		ConnTimeout time.Duration `toml:"connection-timeout"`
 29		MaxDataSize string        `toml:"max-data-size"`
 30	} `toml:"lmtp"`
 31
 32	Storage struct {
 33		Driver string `toml:"driver"`
 34		DSN    string `toml:"dsn"`
 35	} `toml:"storage"`
 36
 37	SMTP struct {
 38		Address      string `toml:"address"`
 39		ConnType     string `toml:"connection-type"`
 40		AuthUser     string `toml:"username"`
 41		AuthPassword string `toml:"password"`
 42		Sender       string `toml:"sender"`
 43	} `toml:"smtp"`
 44}
 45
 46var DefaultConfig = &Config{
 47	Log: struct {
 48		Level string `toml:"level"`
 49	}{"info"},
 50	Storage: struct {
 51		Driver string `toml:"driver"`
 52		DSN    string `toml:"dsn"`
 53	}{"sqlite3", "./mlisting.db"},
 54}
 55
 56func (cfg *Config) NewLogger() Logger {
 57	var leveler slog.Leveler
 58	switch cfg.Log.Level {
 59	case "debug":
 60		leveler = slog.LevelDebug
 61	case "info":
 62		leveler = slog.LevelInfo
 63	case "warn":
 64		leveler = slog.LevelWarn
 65	case "error":
 66		leveler = slog.LevelError
 67	default:
 68		leveler = slog.LevelInfo
 69	}
 70	logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
 71		Level: leveler,
 72	}))
 73	return logger
 74}
 75
 76func (cfg *Config) HttpRealUrl(abs string) (real string) {
 77	if len(abs) > 0 && abs[0] != '/' {
 78		panic("only can get real url from abs path")
 79	}
 80
 81	if cfg.Http.Home != "" {
 82		u, err := url.Parse(cfg.Http.Home)
 83		if err != nil {
 84			panic(err)
 85		}
 86		if abs == "/" {
 87			return u.Path
 88		} else {
 89			real = path.Join(u.Path, abs)
 90		}
 91	} else {
 92		if abs == "/" {
 93			return "/"
 94		} else {
 95			real = path.Join("/", abs)
 96		}
 97	}
 98	if abs[len(abs)-1] == '/' {
 99		real = real + "/"
100	}
101	return
102}
103
104func ParseToml(fpath string) (*Config, error) {
105	f, err := os.Open(fpath)
106	if err != nil {
107		return nil, err
108	}
109	defer f.Close()
110
111	var cfg = new(Config)
112	if _, err := toml.NewDecoder(f).Decode(cfg); err != nil {
113		return nil, err
114	}
115	return cfg, nil
116}
117
118var ContextKey = struct{ key string }{"config"}
119
120func Context(ctx context.Context, cfg *Config) context.Context {
121	return context.WithValue(ctx, ContextKey, cfg)
122}
123
124func FromContext(ctx context.Context) *Config {
125	cfg, ok := ctx.Value(ContextKey).(*Config)
126	if !ok {
127		return DefaultConfig
128	}
129	return cfg
130}