kpaste

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

  1package main
  2
  3import (
  4	"log/slog"
  5	"net/http"
  6	"os"
  7	"time"
  8
  9	"github.com/spf13/cobra"
 10	"github.com/spf13/pflag"
 11)
 12
 13var rootCmd = &cobra.Command{
 14	Use: "pastebin",
 15	PersistentPreRunE: func(*cobra.Command, []string) error {
 16		InitLogger()
 17		return nil
 18	},
 19	CompletionOptions: cobra.CompletionOptions{
 20		DisableDefaultCmd: true,
 21	},
 22}
 23
 24var globalFlags struct {
 25	Debug bool
 26}
 27
 28func init() {
 29	f := rootCmd.PersistentFlags()
 30	f.BoolVar(&globalFlags.Debug, "debug", false, "debug log output")
 31
 32	rootCmd.AddCommand(
 33		serveCmd,
 34		cleanCmd,
 35	)
 36
 37}
 38
 39func main() {
 40	if err := rootCmd.Execute(); err != nil {
 41		slog.Error(err.Error())
 42		os.Exit(1)
 43	}
 44}
 45
 46var serveCmd = &cobra.Command{
 47	Use:   "serve",
 48	Short: "start http service",
 49	RunE:  Serve,
 50}
 51
 52var serveFlags struct {
 53	Listen                string
 54	DB                    string
 55	Media                 string
 56	MOTD                  string
 57	UploadLimit           int
 58	DefaultExpireDuration time.Duration
 59}
 60
 61func init() {
 62	var f *pflag.FlagSet
 63	f = serveCmd.Flags()
 64	f.StringVarP(&serveFlags.Listen, "listen", "l", "127.0.0.1:15700", "listen address")
 65	f.StringVar(&serveFlags.DB, "db", "./data.db", "database file path")
 66	f.StringVar(&serveFlags.Media, "media", "", "directory to store upload files")
 67	f.StringVar(&serveFlags.MOTD, "motd", "motd", "the note key for hode motd")
 68	f.IntVar(&serveFlags.UploadLimit, "upload-limit", 5012, "max upload body size (unit: kilobyte)")
 69	f.DurationVar(&serveFlags.DefaultExpireDuration, "expire", time.Hour*24*30, "default expire duration")
 70
 71	f = cleanCmd.Flags()
 72	f.StringVar(&serveFlags.DB, "db", "./data.db", "database file path")
 73	f.StringVar(&serveFlags.Media, "media", "", "directory to store upload files")
 74}
 75
 76func Serve(cmd *cobra.Command, args []string) error {
 77	db, err := NewSqliteDB(serveFlags.DB)
 78	if err != nil {
 79		return err
 80	}
 81
 82	var fs MediaFS
 83	if serveFlags.Media != "" {
 84		fs = NewLocalFS(serveFlags.Media)
 85		db = DBWithExternFS(db, fs)
 86	}
 87
 88	mux, err := NewMux(db)
 89	if err != nil {
 90		return err
 91	}
 92
 93	slog.Info("http service start", "listen", serveFlags.Listen)
 94
 95	return http.ListenAndServe(serveFlags.Listen, mux)
 96}
 97
 98var cleanCmd = &cobra.Command{
 99	Use:   "clean",
100	Short: "clean expired data",
101	RunE:  Clean,
102}
103
104var cleanFlags struct {
105}
106
107func Clean(cmd *cobra.Command, args []string) error {
108	db, err := NewSqliteDB(serveFlags.DB)
109	if err != nil {
110		return err
111	}
112
113	var fs MediaFS
114	if serveFlags.Media != "" {
115		fs = NewLocalFS(serveFlags.Media)
116		db = DBWithExternFS(db, fs)
117	}
118
119	notes, err := db.CleanCache(cmd.Context())
120	if err != nil {
121		return err
122	}
123
124	for key, _ := range notes {
125		cmd.Printf("Cleaned [%s]\n", key)
126	}
127	return nil
128}
129
130func InitLogger() {
131	var l *slog.Logger
132	if globalFlags.Debug {
133		h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug})
134		l = slog.New(h)
135	} else {
136		h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelInfo})
137		l = slog.New(h)
138	}
139	slog.SetDefault(l)
140}