repos / pico

pico services - prose.sh, pastes.sh, imgs.sh, feeds.sh, pgs.sh
git clone https://github.com/picosh/pico.git

pico / prose
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}