1package main23import (4 "log/slog"5 "net/http"6 "os"7 "time"89 "github.com/spf13/cobra"10 "github.com/spf13/pflag"11)1213var rootCmd = &cobra.Command{14 Use: "pastebin",15 PersistentPreRunE: func(*cobra.Command, []string) error {16 InitLogger()17 return nil18 },19 CompletionOptions: cobra.CompletionOptions{20 DisableDefaultCmd: true,21 },22}2324var globalFlags struct {25 Debug bool26}2728func init() {29 f := rootCmd.PersistentFlags()30 f.BoolVar(&globalFlags.Debug, "debug", false, "debug log output")3132 rootCmd.AddCommand(33 serveCmd,34 cleanCmd,35 )3637}3839func main() {40 if err := rootCmd.Execute(); err != nil {41 slog.Error(err.Error())42 os.Exit(1)43 }44}4546var serveCmd = &cobra.Command{47 Use: "serve",48 Short: "start http service",49 RunE: Serve,50}5152var serveFlags struct {53 Listen string54 DB string55 Media string56 MOTD string57 UploadLimit int58 DefaultExpireDuration time.Duration59}6061func init() {62 var f *pflag.FlagSet63 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")7071 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}7576func Serve(cmd *cobra.Command, args []string) error {77 db, err := NewSqliteDB(serveFlags.DB)78 if err != nil {79 return err80 }8182 var fs MediaFS83 if serveFlags.Media != "" {84 fs = NewLocalFS(serveFlags.Media)85 db = DBWithExternFS(db, fs)86 }8788 mux, err := NewMux(db)89 if err != nil {90 return err91 }9293 slog.Info("http service start", "listen", serveFlags.Listen)9495 return http.ListenAndServe(serveFlags.Listen, mux)96}9798var cleanCmd = &cobra.Command{99 Use: "clean",100 Short: "clean expired data",101 RunE: Clean,102}103104var cleanFlags struct {105}106107func Clean(cmd *cobra.Command, args []string) error {108 db, err := NewSqliteDB(serveFlags.DB)109 if err != nil {110 return err111 }112113 var fs MediaFS114 if serveFlags.Media != "" {115 fs = NewLocalFS(serveFlags.Media)116 db = DBWithExternFS(db, fs)117 }118119 notes, err := db.CleanCache(cmd.Context())120 if err != nil {121 return err122 }123124 for key, _ := range notes {125 cmd.Printf("Cleaned [%s]\n", key)126 }127 return nil128}129130func InitLogger() {131 var l *slog.Logger132 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}