Eric Bower
·
2025-05-25
cli.go
1package feeds
2
3import (
4 "fmt"
5 "text/tabwriter"
6 "time"
7
8 "github.com/picosh/pico/pkg/db"
9 "github.com/picosh/pico/pkg/pssh"
10 "github.com/picosh/pico/pkg/shared"
11)
12
13func Middleware(dbpool db.DB, cfg *shared.ConfigSite) pssh.SSHServerMiddleware {
14 return func(next pssh.SSHServerHandler) pssh.SSHServerHandler {
15 return func(sesh *pssh.SSHServerConnSession) error {
16 args := sesh.Command()
17
18 logger := pssh.GetLogger(sesh)
19 user := pssh.GetUser(sesh)
20
21 if user == nil {
22 err := fmt.Errorf("user not found")
23 _, _ = fmt.Fprintln(sesh.Stderr(), err)
24 return err
25 }
26
27 cmd := "help"
28 if len(args) > 0 {
29 cmd = args[0]
30 }
31
32 switch cmd {
33 case "help":
34 _, _ = fmt.Fprintf(sesh, "Commands: [help, ls, rm, run]\r\n\r\n")
35 writer := tabwriter.NewWriter(sesh, 0, 0, 1, ' ', tabwriter.TabIndent)
36 _, _ = fmt.Fprintln(writer, "Cmd\tDesc")
37 _, _ = fmt.Fprintf(
38 writer,
39 "%s\t%s\r\n",
40 "help", "this help text",
41 )
42 _, _ = fmt.Fprintf(
43 writer,
44 "%s\t%s\r\n",
45 "ls", "list feed digest posts with metadata",
46 )
47 _, _ = fmt.Fprintf(
48 writer,
49 "%s\t%s\r\n",
50 "rm {filename}", "removes feed digest post",
51 )
52 _, _ = fmt.Fprintf(
53 writer,
54 "%s\t%s\r\n",
55 "run {filename}", "runs the feed digest post immediately, ignoring last digest time validation",
56 )
57 return writer.Flush()
58 case "ls":
59 posts, err := dbpool.FindPostsForUser(&db.Pager{Page: 0, Num: 1000}, user.ID, "feeds")
60 if err != nil {
61 _, _ = fmt.Fprintln(sesh.Stderr(), err)
62 return err
63 }
64
65 if len(posts.Data) == 0 {
66 _, _ = fmt.Fprintln(sesh, "no posts found")
67 }
68
69 writer := tabwriter.NewWriter(sesh, 0, 0, 1, ' ', tabwriter.TabIndent)
70 _, _ = fmt.Fprintln(writer, "Filename\tLast Digest\tNext Digest\tInterval\tFailed Attempts")
71 for _, post := range posts.Data {
72 parsed := shared.ListParseText(post.Text)
73 digestOption := DigestOptionToTime(*post.Data.LastDigest, parsed.DigestInterval)
74 _, _ = fmt.Fprintf(
75 writer,
76 "%s\t%s\t%s\t%s\t%d/10\r\n",
77 post.Filename,
78 post.Data.LastDigest.Format(time.RFC3339),
79 digestOption.Format(time.RFC3339),
80 parsed.DigestInterval,
81 post.Data.Attempts,
82 )
83 }
84 return writer.Flush()
85 case "rm":
86 filename := args[1]
87 _, _ = fmt.Fprintf(sesh, "removing digest post %s\r\n", filename)
88 write := false
89 if len(args) > 2 {
90 writeRaw := args[2]
91 if writeRaw == "--write" {
92 write = true
93 }
94 }
95
96 post, err := dbpool.FindPostWithFilename(filename, user.ID, "feeds")
97 if err != nil {
98 _, _ = fmt.Fprintln(sesh.Stderr(), err)
99 return err
100 }
101 if write {
102 err = dbpool.RemovePosts([]string{post.ID})
103 if err != nil {
104 _, _ = fmt.Fprintln(sesh.Stderr(), err)
105 }
106 }
107 _, _ = fmt.Fprintf(sesh, "digest post removed %s\r\n", filename)
108 if !write {
109 _, _ = fmt.Fprintln(sesh, "WARNING: *must* append with `--write` for the changes to persist.")
110 }
111 return err
112 case "run":
113 if len(args) < 2 {
114 err := fmt.Errorf("must provide filename of post to run")
115 _, _ = fmt.Fprintln(sesh.Stderr(), err)
116 return err
117 }
118 filename := args[1]
119 post, err := dbpool.FindPostWithFilename(filename, user.ID, "feeds")
120 if err != nil {
121 _, _ = fmt.Fprintln(sesh.Stderr(), err)
122 return err
123 }
124 _, _ = fmt.Fprintf(sesh, "running feed post: %s\r\n", filename)
125 fetcher := NewFetcher(dbpool, cfg)
126 err = fetcher.RunPost(logger, user, post, true)
127 if err != nil {
128 _, _ = fmt.Fprintln(sesh.Stderr(), err)
129 }
130 return err
131 }
132
133 return next(sesh)
134 }
135 }
136}