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