repos / pico

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

commit
8186562
parent
ca1672d
author
Eric Bower
date
2024-03-02 04:02:56 +0000 UTC
fix(pgs): sort rss feed

feat(pgs): add new updated_at rss feed
3 files changed,  +69, -59
M db/db.go
+1, -1
1@@ -341,7 +341,7 @@ type DB interface {
2 	FindProjectLinks(userID, name string) ([]*Project, error)
3 	FindProjectsByUser(userID string) ([]*Project, error)
4 	FindProjectsByPrefix(userID, name string) ([]*Project, error)
5-	FindAllProjects(page *Pager) (*Paginate[*Project], error)
6+	FindAllProjects(page *Pager, by string) (*Paginate[*Project], error)
7 
8 	Close() error
9 }
M db/postgres/storage.go
+12, -12
 1@@ -253,17 +253,11 @@ const (
 2 	sqlRemoveKeys          = `DELETE FROM public_keys WHERE id = ANY($1::uuid[])`
 3 	sqlRemoveUsers         = `DELETE FROM app_users WHERE id = ANY($1::uuid[])`
 4 
 5-	sqlInsertProject      = `INSERT INTO projects (user_id, name, project_dir) VALUES ($1, $2, $3) RETURNING id;`
 6-	sqlUpdateProject      = `UPDATE projects SET updated_at = $3 WHERE user_id = $1 AND name = $2;`
 7-	sqlUpdateProjectAcl   = `UPDATE projects SET acl = $3, updated_at = $4 WHERE user_id = $1 AND name = $2;`
 8-	sqlFindProjectByName  = `SELECT id, user_id, name, project_dir, acl, created_at, updated_at FROM projects WHERE user_id = $1 AND name = $2;`
 9-	sqlSelectProjectCount = `SELECT count(id) FROM projects`
10-	sqlFindAllProjects    = `
11-	SELECT projects.id, user_id, app_users.name as username, projects.name, project_dir, projects.acl, projects.created_at, projects.updated_at
12-	FROM projects
13-	LEFT JOIN app_users ON app_users.id = projects.user_id
14-	ORDER BY created_at ASC
15-	LIMIT $1 OFFSET $2`
16+	sqlInsertProject        = `INSERT INTO projects (user_id, name, project_dir) VALUES ($1, $2, $3) RETURNING id;`
17+	sqlUpdateProject        = `UPDATE projects SET updated_at = $3 WHERE user_id = $1 AND name = $2;`
18+	sqlUpdateProjectAcl     = `UPDATE projects SET acl = $3, updated_at = $4 WHERE user_id = $1 AND name = $2;`
19+	sqlFindProjectByName    = `SELECT id, user_id, name, project_dir, acl, created_at, updated_at FROM projects WHERE user_id = $1 AND name = $2;`
20+	sqlSelectProjectCount   = `SELECT count(id) FROM projects`
21 	sqlFindProjectsByUser   = `SELECT id, user_id, name, project_dir, acl, created_at, updated_at FROM projects WHERE user_id = $1 ORDER BY name ASC, updated_at DESC;`
22 	sqlFindProjectsByPrefix = `SELECT id, user_id, name, project_dir, acl, created_at, updated_at FROM projects WHERE user_id = $1 AND name = project_dir AND name ILIKE $2 ORDER BY updated_at ASC, name ASC;`
23 	sqlFindProjectLinks     = `SELECT id, user_id, name, project_dir, acl, created_at, updated_at FROM projects WHERE user_id = $1 AND name != project_dir AND project_dir = $2 ORDER BY name ASC;`
24@@ -1463,8 +1457,14 @@ func (me *PsqlDB) FindProjectsByUser(userID string) ([]*db.Project, error) {
25 	return projects, nil
26 }
27 
28-func (me *PsqlDB) FindAllProjects(page *db.Pager) (*db.Paginate[*db.Project], error) {
29+func (me *PsqlDB) FindAllProjects(page *db.Pager, by string) (*db.Paginate[*db.Project], error) {
30 	var projects []*db.Project
31+	sqlFindAllProjects := fmt.Sprintf(`
32+	SELECT projects.id, user_id, app_users.name as username, projects.name, project_dir, projects.acl, projects.created_at, projects.updated_at
33+	FROM projects
34+	LEFT JOIN app_users ON app_users.id = projects.user_id
35+	ORDER BY %s DESC
36+	LIMIT $1 OFFSET $2`, by)
37 	rs, err := me.Db.Query(sqlFindAllProjects, page.Num, page.Num*page.Page)
38 	if err != nil {
39 		return nil, err
M pgs/api.go
+56, -46
  1@@ -87,58 +87,67 @@ type RssData struct {
  2 	Contents template.HTML
  3 }
  4 
  5-func rssHandler(w http.ResponseWriter, r *http.Request) {
  6-	dbpool := shared.GetDB(r)
  7-	logger := shared.GetLogger(r)
  8-	cfg := shared.GetCfg(r)
  9+func createRssHandler(by string) http.HandlerFunc {
 10+	return func(w http.ResponseWriter, r *http.Request) {
 11+		dbpool := shared.GetDB(r)
 12+		logger := shared.GetLogger(r)
 13+		cfg := shared.GetCfg(r)
 14 
 15-	pager, err := dbpool.FindAllProjects(&db.Pager{Num: 50, Page: 0})
 16-	if err != nil {
 17-		logger.Error(err.Error())
 18-		http.Error(w, err.Error(), http.StatusInternalServerError)
 19-		return
 20-	}
 21+		pager, err := dbpool.FindAllProjects(&db.Pager{Num: 100, Page: 0}, by)
 22+		if err != nil {
 23+			logger.Error(err.Error())
 24+			http.Error(w, err.Error(), http.StatusInternalServerError)
 25+			return
 26+		}
 27 
 28-	feed := &feeds.Feed{
 29-		Title:       fmt.Sprintf("%s discovery feed", cfg.Domain),
 30-		Link:        &feeds.Link{Href: cfg.ReadURL()},
 31-		Description: fmt.Sprintf("%s latest projects", cfg.Domain),
 32-		Author:      &feeds.Author{Name: cfg.Domain},
 33-		Created:     time.Now(),
 34-	}
 35+		feed := &feeds.Feed{
 36+			Title:       fmt.Sprintf("%s discovery feed %s", cfg.Domain, by),
 37+			Link:        &feeds.Link{Href: cfg.ReadURL()},
 38+			Description: fmt.Sprintf("%s projects %s", cfg.Domain, by),
 39+			Author:      &feeds.Author{Name: cfg.Domain},
 40+			Created:     time.Now(),
 41+		}
 42 
 43-	var feedItems []*feeds.Item
 44-	for _, project := range pager.Data {
 45-		realUrl := strings.TrimSuffix(
 46-			cfg.AssetURL(project.Username, project.Name, ""),
 47-			"/",
 48-		)
 49+		var feedItems []*feeds.Item
 50+		for _, project := range pager.Data {
 51+			realUrl := strings.TrimSuffix(
 52+				cfg.AssetURL(project.Username, project.Name, ""),
 53+				"/",
 54+			)
 55+			uat := project.UpdatedAt.Unix()
 56+			id := realUrl
 57+			title := fmt.Sprintf("%s-%s", project.Username, project.Name)
 58+			if by == "updated_at" {
 59+				id = fmt.Sprintf("%s:%d", realUrl, uat)
 60+				title = fmt.Sprintf("%s - %d", title, uat)
 61+			}
 62 
 63-		item := &feeds.Item{
 64-			Id:          realUrl,
 65-			Title:       project.Name,
 66-			Link:        &feeds.Link{Href: realUrl},
 67-			Content:     fmt.Sprintf(`<a href="%s">%s</a>`, realUrl, realUrl),
 68-			Created:     *project.CreatedAt,
 69-			Updated:     *project.CreatedAt,
 70-			Description: "",
 71-			Author:      &feeds.Author{Name: project.Username},
 72-		}
 73+			item := &feeds.Item{
 74+				Id:          id,
 75+				Title:       title,
 76+				Link:        &feeds.Link{Href: realUrl},
 77+				Content:     fmt.Sprintf(`<a href="%s">%s</a>`, realUrl, realUrl),
 78+				Created:     *project.CreatedAt,
 79+				Updated:     *project.CreatedAt,
 80+				Description: "",
 81+				Author:      &feeds.Author{Name: project.Username},
 82+			}
 83 
 84-		feedItems = append(feedItems, item)
 85-	}
 86-	feed.Items = feedItems
 87+			feedItems = append(feedItems, item)
 88+		}
 89+		feed.Items = feedItems
 90 
 91-	rss, err := feed.ToAtom()
 92-	if err != nil {
 93-		logger.Error(err.Error())
 94-		http.Error(w, "Could not generate atom rss feed", http.StatusInternalServerError)
 95-	}
 96+		rss, err := feed.ToAtom()
 97+		if err != nil {
 98+			logger.Error(err.Error())
 99+			http.Error(w, "Could not generate atom rss feed", http.StatusInternalServerError)
100+		}
101 
102-	w.Header().Add("Content-Type", "application/atom+xml")
103-	_, err = w.Write([]byte(rss))
104-	if err != nil {
105-		logger.Error(err.Error())
106+		w.Header().Add("Content-Type", "application/atom+xml")
107+		_, err = w.Write([]byte(rss))
108+		if err != nil {
109+			logger.Error(err.Error())
110+		}
111 	}
112 }
113 
114@@ -449,7 +458,8 @@ var mainRoutes = []shared.Route{
115 
116 	shared.NewRoute("GET", "/", shared.CreatePageHandler("html/marketing.page.tmpl")),
117 	shared.NewRoute("GET", "/check", checkHandler),
118-	shared.NewRoute("GET", "/rss", rssHandler),
119+	shared.NewRoute("GET", "/rss/updated", createRssHandler("updated_at")),
120+	shared.NewRoute("GET", "/rss", createRssHandler("created_at")),
121 	shared.NewRoute("GET", "/(.+)", shared.CreatePageHandler("html/marketing.page.tmpl")),
122 }
123