pico

created pr with 41.1 on 2025-01-10T15:10:28Z · by c8ef7d19
added 41.2 on 2025-01-10T15:14:05Z · by c8ef7d19
1: 5d5b1f5 ! 1: a6f10fc chore(feeds): better error handling for invalid feed files
cmds
checkout latest patchset:
ssh pr.pico.sh print 41 | git am -3
checkout any patchset in a patch request:
ssh pr.pico.sh print 41.[rev] | git am -3
add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 41
+20 -9 feeds/cron.go #
......@@ -9,6 +9,7 @@ import (
99 "log/slog"
1010 "math"
1111 "net/http"
12+ "net/url"
1213 "strings"
1314 "text/template"
1415 "time"
......@@ -161,23 +162,29 @@ func (f *Fetcher) RunPost(logger *slog.Logger, user *db.User, post *db.Post) err
161162
162163 urls := []string{}
163164 for _, item := range parsed.Items {
164- url := ""
165- if item.IsText {
166- url = item.Value
165+ u := ""
166+ if item.IsText || item.IsURL {
167+ u = item.Value
167168 } else if item.IsURL {
168- url = string(item.URL)
169+ u = string(item.Value)
169170 }
170171
171- if url == "" {
172+ if u == "" {
172173 continue
173174 }
174175
175- urls = append(urls, url)
176+ _, err := url.Parse(string(item.URL))
177+ if err != nil {
178+ logger.Info("invalid url", "url", string(item.URL))
179+ continue
180+ }
181+
182+ urls = append(urls, u)
176183 }
177184
178185 now := time.Now().UTC()
179186 if post.ExpiresAt == nil {
180- expiresAt := time.Now().AddDate(0, 6, 0)
187+ expiresAt := time.Now().AddDate(0, 12, 0)
181188 post.ExpiresAt = &expiresAt
182189 }
183190 _, err = f.db.UpdatePost(post)
......@@ -199,7 +206,7 @@ func (f *Fetcher) RunPost(logger *slog.Logger, user *db.User, post *db.Post) err
199206 post.Data.Attempts += 1
200207 logger.Error("could not fetch urls", "err", err, "attempts", post.Data.Attempts)
201208
202- errBody := fmt.Sprintf(`There was an error attempting to fetch your feeds (%d) times. After (3) attempts we remove the file from our system. Please check all the URLs and re-upload.
209+ errBody := fmt.Sprintf(`There was an error attempting to fetch your feeds (%d) times. After (5) attempts we remove the file from our system. Please check all the URLs and re-upload.
203210 Also, we have centralized logs in our pico.sh TUI that will display realtime feed errors so you can debug.
204211
205212
......@@ -217,7 +224,7 @@ Also, we have centralized logs in our pico.sh TUI that will display realtime fee
217224 return err
218225 }
219226
220- if post.Data.Attempts >= 3 {
227+ if post.Data.Attempts >= 5 {
221228 err = f.db.RemovePosts([]string{post.ID})
222229 if err != nil {
223230 return err
......@@ -410,6 +417,10 @@ func (f *Fetcher) FetchAll(logger *slog.Logger, urls []string, inlineContent boo
410417 return nil, err
411418 }
412419
420+ if len(urls) == 0 {
421+ return nil, fmt.Errorf("feed file does not contain any urls")
422+ }
423+
413424 var allErrors error
414425 for _, url := range urls {
415426 feedTmpl, err := f.Fetch(logger, fp, url, username, feedItems)
+33 -14 feeds/scp_hooks.go #
......@@ -1,12 +1,13 @@
11 package feeds
22
33 import (
4+ "errors"
45 "fmt"
6+ "net/url"
7+
58 "strings"
69 "time"
710
8- "slices"
9-
1011 "github.com/charmbracelet/ssh"
1112 "github.com/picosh/pico/db"
1213 "github.com/picosh/pico/filehandlers"
......@@ -38,23 +39,41 @@ func (p *FeedHooks) FileValidate(s ssh.Session, data *filehandlers.PostMetaData)
3839 return false, err
3940 }
4041
41- return true, nil
42-}
43-
44-func (p *FeedHooks) FileMeta(s ssh.Session, data *filehandlers.PostMetaData) error {
45- parsedText := shared.ListParseText(string(data.Text))
42+ // Because we need to support sshfs, sftp runs our Write handler twice
43+ // and on the first pass we do not have access to the file data.
44+ // In that case we should skip the parsing validation
45+ if data.Text == "" {
46+ return true, nil
47+ }
4648
47- if parsedText.Title == "" {
48- data.Title = utils.ToUpper(data.Slug)
49- } else {
50- data.Title = parsedText.Title
49+ parsed := shared.ListParseText(string(data.Text))
50+ if parsed.Email == "" {
51+ return false, fmt.Errorf("ERROR: no email variable detected for %s, check the format of your file, skipping", data.Filename)
5152 }
5253
53- data.Description = parsedText.Description
54- data.Tags = parsedText.Tags
54+ var allErr error
55+ for _, txt := range parsed.Items {
56+ u := ""
57+ if txt.IsText {
58+ u = txt.Value
59+ } else if txt.IsURL {
60+ u = string(txt.URL)
61+ }
5562
56- data.Hidden = slices.Contains(p.Cfg.HiddenPosts, data.Filename)
63+ _, err := url.Parse(u)
64+ if err != nil {
65+ allErr = errors.Join(allErr, fmt.Errorf("%s: %w", u, err))
66+ continue
67+ }
68+ }
69+ if allErr != nil {
70+ return false, fmt.Errorf("ERROR: some urls provided were invalid check the format of your file, skipping: %w", allErr)
71+ }
72+
73+ return true, nil
74+}
5775
76+func (p *FeedHooks) FileMeta(s ssh.Session, data *filehandlers.PostMetaData) error {
5877 if data.Data.LastDigest == nil {
5978 now := time.Now()
6079 data.Data.LastDigest = &now
Back to top