Added feeds for crossposting and a rebuild site button

This commit is contained in:
Leon Mika 2026-03-08 09:37:49 +11:00
parent 76ed54f119
commit fa9be69045
6 changed files with 62 additions and 11 deletions

View file

@ -125,6 +125,9 @@ Starting weiro without any arguments will start the server.
siteGroup.Patch("/posts/:postID", ph.Patch) siteGroup.Patch("/posts/:postID", ph.Patch)
siteGroup.Delete("/posts/:postID", ph.Delete) siteGroup.Delete("/posts/:postID", ph.Delete)
// TODO Move
siteGroup.Post("/rebuild", ph.Rebuild)
siteGroup.Get("/uploads", uh.Index) siteGroup.Get("/uploads", uh.Index)
siteGroup.Get("/uploads/slug/+", uh.ShowFromSlug) siteGroup.Get("/uploads/slug/+", uh.ShowFromSlug)
siteGroup.Get("/uploads/:uploadID", uh.Show) siteGroup.Get("/uploads/:uploadID", uh.Show)

View file

@ -149,6 +149,18 @@ func (ph PostsHandler) Delete(c fiber.Ctx) error {
return accepts(c, json(func() any { return accepts(c, json(func() any {
return fiber.Map{} return fiber.Map{}
}), html(func(c fiber.Ctx) error { }), html(func(c fiber.Ctx) error {
return c.Redirect().To("/sites") return c.Redirect().To("/")
}))
}
func (ph PostsHandler) Rebuild(c fiber.Ctx) error {
if err := ph.PostService.RebuildSite(c.Context()); err != nil {
return err
}
return accepts(c, json(func() any {
return fiber.Map{}
}), html(func(c fiber.Ctx) error {
return c.Redirect().To("/")
})) }))
} }

View file

@ -72,7 +72,17 @@ func (b *Builder) BuildSite(outDir string) error {
}) })
eg.Go(func() error { eg.Go(func() error {
if err := b.renderFeeds(buildCtx, b.site.PostIter(ctx)); err != nil { if err := b.renderFeeds(buildCtx, b.site.PostIter(ctx), feedOptions{
targetNamePrefix: "/feed",
titlePrefix: "",
}); err != nil {
return err
}
if err := b.renderFeeds(buildCtx, b.site.PostIter(ctx), feedOptions{
targetNamePrefix: "/feeds/microblog-crosspost",
titlePrefix: "Devlog: ",
}); err != nil {
return err return err
} }
return nil return nil
@ -119,7 +129,7 @@ func (b *Builder) renderPostList(ctx buildContext, postIter iter.Seq[models.Mayb
}) })
} }
func (b *Builder) renderFeeds(ctx buildContext, postIter iter.Seq[models.Maybe[*models.Post]]) error { func (b *Builder) renderFeeds(ctx buildContext, postIter iter.Seq[models.Maybe[*models.Post]], opts feedOptions) error {
now := time.Now() now := time.Now()
feed := &feedhub.Feed{ feed := &feedhub.Feed{
Title: b.site.Title, Title: b.site.Title,
@ -141,9 +151,14 @@ func (b *Builder) renderFeeds(ctx buildContext, postIter iter.Seq[models.Maybe[*
return err return err
} }
postTitle := post.Title
if postTitle != "" {
postTitle = opts.titlePrefix + postTitle
}
feed.Items = append(feed.Items, &feedhub.Item{ feed.Items = append(feed.Items, &feedhub.Item{
Id: filepath.Join(b.site.BaseURL, post.GUID), Id: filepath.Join(b.site.BaseURL, post.GUID),
Title: post.Title, Title: postTitle,
Link: &feedhub.Link{Href: renderedPost.PostURL}, Link: &feedhub.Link{Href: renderedPost.PostURL},
Content: string(renderedPost.HTML), Content: string(renderedPost.HTML),
// TO FIX: Created should be first published // TO FIX: Created should be first published
@ -157,7 +172,7 @@ func (b *Builder) renderFeeds(ctx buildContext, postIter iter.Seq[models.Maybe[*
} }
} }
if err := b.createAtPath(ctx, "/feed.xml", func(f io.Writer) error { if err := b.createAtPath(ctx, opts.targetNamePrefix+".xml", func(f io.Writer) error {
rss, err := feed.ToRss() rss, err := feed.ToRss()
if err != nil { if err != nil {
return fmt.Errorf("failed to convert feed to RSS: %w", err) return fmt.Errorf("failed to convert feed to RSS: %w", err)
@ -168,7 +183,7 @@ func (b *Builder) renderFeeds(ctx buildContext, postIter iter.Seq[models.Maybe[*
return err return err
} }
if err := b.createAtPath(ctx, "/feed.json", func(f io.Writer) error { if err := b.createAtPath(ctx, opts.targetNamePrefix+".json", func(f io.Writer) error {
rss, err := feed.ToJSON() rss, err := feed.ToJSON()
if err != nil { if err != nil {
return fmt.Errorf("failed to convert feed to JSON feed: %w", err) return fmt.Errorf("failed to convert feed to JSON feed: %w", err)
@ -276,7 +291,3 @@ func (b *Builder) writeUploads(ctx buildContext, uploads []models.Upload) error
} }
return nil return nil
} }
type buildContext struct {
outDir string
}

View file

@ -0,0 +1,10 @@
package sitebuilder
type buildContext struct {
outDir string
}
type feedOptions struct {
targetNamePrefix string
titlePrefix string
}

View file

@ -79,3 +79,13 @@ func (s *Service) fetchOrCreatePost(ctx context.Context, site models.Site, param
} }
return post, nil return post, nil
} }
// TEMP - to move
func (s *Service) RebuildSite(ctx context.Context) error {
site, ok := models.GetSite(ctx)
if !ok {
return models.SiteRequiredError
}
s.publisher.Queue(site)
return nil
}

View file

@ -1,7 +1,12 @@
{{ $showingTrash := eq .req.Filter "deleted" }} {{ $showingTrash := eq .req.Filter "deleted" }}
<main class="container"> <main class="container">
<div class="my-4 d-flex justify-content-between align-items-baseline"> <div class="my-4 d-flex justify-content-between align-items-baseline">
<a href="/sites/{{ .site.ID }}/posts/new" class="btn btn-success">New Post</a> <div>
<a href="/sites/{{ .site.ID }}/posts/new" class="btn btn-success">New Post</a>
<form action="/sites/{{ .site.ID }}/rebuild" method="post" style="display: inline-block;">
<input type="submit" class="btn btn-outline-primary" value="Rebuild Site">
</form>
</div>
<div> <div>
<div class="btn-group" role="group" aria-label="First group"> <div class="btn-group" role="group" aria-label="First group">