Eric Bower
·
29 Nov 24
cli.go
1package prose
2
3import (
4 "fmt"
5 "log/slog"
6 "strings"
7
8 "github.com/charmbracelet/ssh"
9 "github.com/charmbracelet/wish"
10 bm "github.com/charmbracelet/wish/bubbletea"
11 "github.com/muesli/termenv"
12 "github.com/picosh/pico/db"
13 "github.com/picosh/pico/tui/common"
14 "github.com/picosh/utils"
15)
16
17func getUser(s ssh.Session, dbpool db.DB) (*db.User, error) {
18 if s.PublicKey() == nil {
19 return nil, fmt.Errorf("key not found")
20 }
21
22 key := utils.KeyForKeyText(s.PublicKey())
23
24 user, err := dbpool.FindUserForKey(s.User(), key)
25 if err != nil {
26 return nil, err
27 }
28
29 if user.Name == "" {
30 return nil, fmt.Errorf("must have username set")
31 }
32
33 return user, nil
34}
35
36type Cmd struct {
37 User *db.User
38 Session utils.CmdSession
39 Log *slog.Logger
40 Dbpool db.DB
41 Styles common.Styles
42 Width int
43 Height int
44}
45
46func (c *Cmd) output(out string) {
47 _, _ = c.Session.Write([]byte(out + "\r\n"))
48}
49
50func (c *Cmd) help() {
51 helpStr := "Commands: [help, stats]\n"
52 c.output(helpStr)
53}
54
55func (c *Cmd) statsByPost(_ string) error {
56 msg := fmt.Sprintf(
57 "%s\n\nRun %s to access pico's analytics TUI",
58 c.Styles.Logo.Render("DEPRECATED"),
59 c.Styles.Code.Render("ssh pico.sh"),
60 )
61 c.output(c.Styles.RoundedBorder.Render(msg))
62 return nil
63}
64
65func (c *Cmd) stats() error {
66 return c.statsByPost("")
67}
68
69type CliHandler struct {
70 DBPool db.DB
71 Logger *slog.Logger
72}
73
74func WishMiddleware(handler *CliHandler) wish.Middleware {
75 dbpool := handler.DBPool
76 log := handler.Logger
77
78 return func(next ssh.Handler) ssh.Handler {
79 return func(sesh ssh.Session) {
80 args := sesh.Command()
81 if len(args) == 0 {
82 next(sesh)
83 return
84 }
85
86 // default width and height when no pty
87 width := 80
88 height := 24
89 pty, _, ok := sesh.Pty()
90 if ok {
91 width = pty.Window.Width
92 height = pty.Window.Height
93 }
94
95 user, err := getUser(sesh, dbpool)
96 if err != nil {
97 wish.Errorln(sesh, err)
98 return
99 }
100
101 renderer := bm.MakeRenderer(sesh)
102 renderer.SetColorProfile(termenv.TrueColor)
103 styles := common.DefaultStyles(renderer)
104
105 opts := Cmd{
106 Session: sesh,
107 User: user,
108 Log: log,
109 Dbpool: dbpool,
110 Styles: styles,
111 Width: width,
112 Height: height,
113 }
114
115 cmd := strings.TrimSpace(args[0])
116 if len(args) == 1 {
117 if cmd == "help" {
118 opts.help()
119 return
120 } else if cmd == "stats" {
121 err := opts.stats()
122 if err != nil {
123 wish.Fatalln(sesh, err)
124 }
125 return
126 } else {
127 next(sesh)
128 return
129 }
130 }
131
132 postSlug := strings.TrimSpace(args[1])
133 cmdArgs := args[2:]
134 log.Info(
135 "pgs middleware detected command",
136 "args", args,
137 "cmd", cmd,
138 "post", postSlug,
139 "cmdArgs", cmdArgs,
140 )
141
142 if cmd == "stats" {
143 err := opts.statsByPost(postSlug)
144 if err != nil {
145 wish.Fatalln(sesh, err)
146 }
147 return
148 } else {
149 next(sesh)
150 return
151 }
152 }
153 }
154}