This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / appview / timeline / router.go
2.2 kB 105 lines
1package timeline 2 3import ( 4 "bytes" 5 "io/fs" 6 "log/slog" 7 "net/http" 8 "os" 9 "strings" 10 11 "github.com/adrg/frontmatter" 12 "github.com/go-chi/chi/v5" 13 "tangled.org/core/appview/config" 14 "tangled.org/core/appview/db" 15 "tangled.org/core/appview/oauth" 16 "tangled.org/core/appview/pages" 17) 18 19type postMeta struct { 20 Slug string `yaml:"slug"` 21 Title string `yaml:"title"` 22 Date string `yaml:"date"` 23 Draft bool `yaml:"draft"` 24} 25 26type Timeline struct { 27 oauth *oauth.OAuth 28 db *db.DB 29 config *config.Config 30 pages *pages.Pages 31 logger *slog.Logger 32 recentPosts []pages.BlogPost 33} 34 35func New( 36 oauth *oauth.OAuth, 37 db *db.DB, 38 config *config.Config, 39 pages *pages.Pages, 40 logger *slog.Logger, 41 postsDir string, 42) *Timeline { 43 t := &Timeline{ 44 oauth: oauth, 45 db: db, 46 config: config, 47 pages: pages, 48 logger: logger, 49 } 50 t.recentPosts = loadRecentPosts(postsDir, logger) 51 return t 52} 53 54func (t *Timeline) Router() http.Handler { 55 r := chi.NewRouter() 56 r.Get("/", t.HomeOrTimeline) 57 r.Get("/home", t.Home) 58 r.Get("/timeline", t.Timeline) 59 return r 60} 61 62func loadRecentPosts(postsDir string, logger *slog.Logger) []pages.BlogPost { 63 fsys := os.DirFS(postsDir) 64 entries, err := fs.ReadDir(fsys, ".") 65 if err != nil { 66 logger.Warn("failed to read blog posts dir", "dir", postsDir, "err", err) 67 return nil 68 } 69 70 var posts []postMeta 71 for _, entry := range entries { 72 if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".md") { 73 continue 74 } 75 data, err := fs.ReadFile(fsys, entry.Name()) 76 if err != nil { 77 continue 78 } 79 var meta postMeta 80 if _, err := frontmatter.Parse(bytes.NewReader(data), &meta); err != nil { 81 continue 82 } 83 if meta.Draft { 84 continue 85 } 86 posts = append(posts, meta) 87 } 88 89 // sort newest-first by date string (format "2006-01-02" sorts lexicographically) 90 for i := 1; i < len(posts); i++ { 91 for j := i; j > 0 && posts[j].Date > posts[j-1].Date; j-- { 92 posts[j], posts[j-1] = posts[j-1], posts[j] 93 } 94 } 95 96 if len(posts) > 3 { 97 posts = posts[:3] 98 } 99 100 result := make([]pages.BlogPost, len(posts)) 101 for i, p := range posts { 102 result[i] = pages.BlogPost{Slug: p.Slug, Title: p.Title, Date: p.Date} 103 } 104 return result 105}