this repo has no description smallweb.run
smallweb
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

add email command in cli

pomdtr b43b4445 554b1237

+114 -11
+1 -1
app/app.go
··· 92 92 return apps, nil 93 93 } 94 94 95 - func NewApp(appname string, rootDir string, domain string, isAdmin bool) (App, error) { 95 + func LoadApp(appname string, rootDir string, domain string, isAdmin bool) (App, error) { 96 96 appDir := filepath.Join(rootDir, appname) 97 97 if !utils.FileExists(filepath.Join(rootDir, appname)) { 98 98 return App{}, ErrAppNotFound
+2 -2
cmd/crons.go
··· 72 72 continue 73 73 } 74 74 75 - app, err := app.NewApp(name, k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), name)) 75 + app, err := app.LoadApp(name, k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), name)) 76 76 if err != nil { 77 77 return fmt.Errorf("failed to load app: %w", err) 78 78 } ··· 149 149 } 150 150 151 151 for _, name := range apps { 152 - a, err := app.NewApp(name, k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), name)) 152 + a, err := app.LoadApp(name, k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), name)) 153 153 if err != nil { 154 154 fmt.Println(err) 155 155 continue
+102
cmd/email.go
··· 1 + package cmd 2 + 3 + import ( 4 + "fmt" 5 + "io" 6 + "os" 7 + "slices" 8 + "strings" 9 + 10 + "github.com/mattn/go-isatty" 11 + "github.com/pomdtr/smallweb/app" 12 + "github.com/pomdtr/smallweb/worker" 13 + "github.com/spf13/cobra" 14 + ) 15 + 16 + type Message struct { 17 + Subject string 18 + From string 19 + To string 20 + Text string 21 + } 22 + 23 + func (me *Message) String() string { 24 + builder := strings.Builder{} 25 + builder.WriteString("Subject: ") 26 + builder.WriteString(me.Subject) 27 + builder.WriteString("\n") 28 + 29 + builder.WriteString("From: ") 30 + builder.WriteString(me.From) 31 + builder.WriteString("\n") 32 + 33 + builder.WriteString("To: ") 34 + builder.WriteString(me.To) 35 + builder.WriteString("\n") 36 + 37 + builder.WriteString("Content-Type: text/plain; charset=utf-8") 38 + 39 + builder.WriteString("\n") 40 + builder.WriteString("\n") 41 + 42 + builder.WriteString(me.Text) 43 + 44 + return builder.String() 45 + } 46 + 47 + func NewCmdEmail() *cobra.Command { 48 + var flags struct { 49 + subject string 50 + from string 51 + body string 52 + } 53 + 54 + cmd := &cobra.Command{ 55 + Use: "email <app>", 56 + Short: "Send an email", 57 + Long: "Send an email to an app", 58 + ValidArgsFunction: completeApp, 59 + Args: cobra.ExactArgs(1), 60 + RunE: func(cmd *cobra.Command, args []string) error { 61 + var text string 62 + if cmd.Flags().Changed("body") { 63 + text = flags.body 64 + } else if !isatty.IsTerminal(os.Stdin.Fd()) { 65 + bytes, err := io.ReadAll(os.Stdin) 66 + if err != nil { 67 + return fmt.Errorf("failed to read from stdin: %w", err) 68 + } 69 + 70 + text = string(bytes) 71 + } else { 72 + return fmt.Errorf("body is required") 73 + } 74 + 75 + message := &Message{ 76 + Subject: flags.subject, 77 + From: flags.from, 78 + To: fmt.Sprintf("%s@%s", args[0], k.String("domain")), 79 + Text: text, 80 + } 81 + 82 + a, err := app.LoadApp(args[0], k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), args[0])) 83 + if err != nil { 84 + return fmt.Errorf("failed to load app: %w", err) 85 + } 86 + 87 + wk := worker.NewWorker(a, k.String("dir"), k.String("domain")) 88 + 89 + if err := wk.SendEmail(cmd.Context(), strings.NewReader(message.String())); err != nil { 90 + return fmt.Errorf("failed to send email: %w", err) 91 + } 92 + 93 + return nil 94 + }, 95 + } 96 + 97 + cmd.Flags().StringVarP(&flags.subject, "subject", "s", "", "Email's subject") 98 + cmd.Flags().StringVarP(&flags.from, "from", "f", "", "Email's sender") 99 + cmd.Flags().StringVarP(&flags.body, "body", "b", "", "Email's body") 100 + 101 + return cmd 102 + }
+1 -1
cmd/fetch.go
··· 52 52 53 53 req.Host = fmt.Sprintf("%s.%s", args[0], k.String("domain")) 54 54 55 - a, err := app.NewApp(args[0], k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), args[0])) 55 + a, err := app.LoadApp(args[0], k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), args[0])) 56 56 if err != nil { 57 57 return fmt.Errorf("failed to load app: %w", err) 58 58 }
+2 -2
cmd/open.go
··· 28 28 return fmt.Errorf("no app specified and not in an app directory") 29 29 } 30 30 31 - a, err := app.NewApp(filepath.Base(cwd), k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), filepath.Base(cwd))) 31 + a, err := app.LoadApp(filepath.Base(cwd), k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), filepath.Base(cwd))) 32 32 if err != nil { 33 33 return fmt.Errorf("failed to load app: %w", err) 34 34 } ··· 40 40 return nil 41 41 } 42 42 43 - a, err := app.NewApp(args[0], k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), args[0])) 43 + a, err := app.LoadApp(args[0], k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), args[0])) 44 44 if err != nil { 45 45 return fmt.Errorf("failed to load app: %w", err) 46 46 }
+1
cmd/root.go
··· 162 162 rootCmd.AddCommand(NewCmdLogs()) 163 163 rootCmd.AddCommand(NewCmdSecrets()) 164 164 rootCmd.AddCommand(NewCmdLink()) 165 + rootCmd.AddCommand(NewCmdEmail()) 165 166 166 167 rootCmd.AddCommand(&cobra.Command{ 167 168 Use: "changelog",
+1 -1
cmd/run.go
··· 24 24 return cmd.Help() 25 25 } 26 26 27 - a, err := app.NewApp(args[0], k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), args[0])) 27 + a, err := app.LoadApp(args[0], k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), args[0])) 28 28 if err != nil { 29 29 return fmt.Errorf("failed to load app: %w", err) 30 30 }
+4 -4
cmd/up.go
··· 99 99 return fmt.Errorf("failed to lookup app: %v", err) 100 100 } 101 101 102 - if _, err := app.NewApp(appname, k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), appname)); err != nil { 102 + if _, err := app.LoadApp(appname, k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), appname)); err != nil { 103 103 return fmt.Errorf("failed to load app: %v", err) 104 104 } 105 105 ··· 170 170 if sess.User() == "_" { 171 171 workDir = k.String("dir") 172 172 } else { 173 - app, err := app.NewApp(sess.User(), k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), sess.User())) 173 + app, err := app.LoadApp(sess.User(), k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), sess.User())) 174 174 if err != nil { 175 175 fmt.Fprintln(sess, "failed to load app:", err) 176 176 return ··· 211 211 cmd = exec.Command(execPath, sess.Command()...) 212 212 cmd.Env = os.Environ() 213 213 } else { 214 - app, err := app.NewApp(sess.User(), k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), sess.User())) 214 + app, err := app.LoadApp(sess.User(), k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), sess.User())) 215 215 if err != nil { 216 216 fmt.Fprintf(sess, "failed to load app: %v\n", err) 217 217 return ··· 437 437 me.mu.Lock() 438 438 defer me.mu.Unlock() 439 439 440 - a, err := app.NewApp(appname, rootDir, domain, slices.Contains(k.Strings("adminApps"), appname)) 440 + a, err := app.LoadApp(appname, rootDir, domain, slices.Contains(k.Strings("adminApps"), appname)) 441 441 if err != nil { 442 442 return nil, fmt.Errorf("failed to load app: %w", err) 443 443 }