Eric Bower
·
2026-01-25
scp_hooks.go
1package feeds
2
3import (
4 "errors"
5 "fmt"
6 "net/url"
7 "strings"
8
9 "github.com/adhocore/gronx"
10 "github.com/picosh/pico/pkg/db"
11 "github.com/picosh/pico/pkg/filehandlers"
12 "github.com/picosh/pico/pkg/pssh"
13 "github.com/picosh/pico/pkg/shared"
14)
15
16type FeedHooks struct {
17 Cfg *shared.ConfigSite
18 Db db.DB
19}
20
21func (p *FeedHooks) FileValidate(s *pssh.SSHServerConnSession, data *filehandlers.PostMetaData) (bool, error) {
22 if !shared.IsTextFile(string(data.Text)) {
23 err := fmt.Errorf(
24 "WARNING: (%s) invalid file must be plain text (utf-8), skipping",
25 data.Filename,
26 )
27 return false, err
28 }
29
30 if !shared.IsExtAllowed(data.Filename, p.Cfg.AllowedExt) {
31 extStr := strings.Join(p.Cfg.AllowedExt, ",")
32 err := fmt.Errorf(
33 "WARNING: (%s) invalid file, format must be (%s), skipping",
34 data.Filename,
35 extStr,
36 )
37 return false, err
38 }
39
40 // Because we need to support sshfs, sftp runs our Write handler twice
41 // and on the first pass we do not have access to the file data.
42 // In that case we should skip the parsing validation
43 if data.Text == "" {
44 return true, nil
45 }
46
47 parsed := shared.ListParseText(string(data.Text))
48 if parsed.Email == "" {
49 return false, fmt.Errorf("ERROR: no email variable detected for %s, check the format of your file, skipping", data.Filename)
50 }
51
52 if parsed.DigestInterval != "" {
53 return false, fmt.Errorf("ERROR: `digest_interval` is deprecated; use `cron`: https://pico.sh/feeds#cron")
54 }
55
56 if parsed.Cron != "" {
57 if !gronx.IsValid(parsed.Cron) {
58 return false, fmt.Errorf("ERROR: `cron` is invalid, reference: https://github.com/adhocore/gronx?tab=readme-ov-file#cron-expression")
59 }
60 }
61
62 var allErr error
63 for _, txt := range parsed.Items {
64 u := ""
65 if txt.IsText {
66 u = txt.Value
67 } else if txt.IsURL {
68 u = string(txt.URL)
69 }
70
71 _, err := url.Parse(u)
72 if err != nil {
73 allErr = errors.Join(allErr, fmt.Errorf("%s: %w", u, err))
74 continue
75 }
76 }
77 if allErr != nil {
78 return false, fmt.Errorf("ERROR: some urls provided were invalid check the format of your file, skipping: %w", allErr)
79 }
80
81 return true, nil
82}
83
84func (p *FeedHooks) FileMeta(s *pssh.SSHServerConnSession, data *filehandlers.PostMetaData) error {
85 return nil
86}