Publish new posts to mailing list
This commit is contained in:
parent
3e67823205
commit
3059909deb
@ -131,11 +131,17 @@ func (a *api) renderPostHandler() http.Handler {
|
||||
|
||||
func (a *api) renderPostsIndexHandler() http.Handler {
|
||||
|
||||
renderEditPostHandler := a.renderEditPostHandler()
|
||||
tpl := a.mustParseBasedTpl("posts.html")
|
||||
const pageCount = 20
|
||||
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if _, ok := r.URL.Query()["edit"]; ok {
|
||||
renderEditPostHandler.ServeHTTP(rw, r)
|
||||
return
|
||||
}
|
||||
|
||||
page, err := apiutil.StrToInt(r.FormValue("p"), 0)
|
||||
if err != nil {
|
||||
apiutil.BadRequest(
|
||||
@ -239,13 +245,28 @@ func (a *api) postPostHandler() http.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
if err := a.params.PostStore.Set(p, time.Now()); err != nil {
|
||||
first, err := a.params.PostStore.Set(p, time.Now())
|
||||
|
||||
if err != nil {
|
||||
apiutil.InternalServerError(
|
||||
rw, r, fmt.Errorf("storing post with id %q: %w", p.ID, err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if first {
|
||||
|
||||
a.params.Logger.Info(r.Context(), "publishing blog post to mailing list")
|
||||
urlStr := a.params.PublicURL.String() + filepath.Join("/posts", p.ID)
|
||||
|
||||
if err := a.params.MailingList.Publish(p.Title, urlStr); err != nil {
|
||||
apiutil.InternalServerError(
|
||||
rw, r, fmt.Errorf("publishing post with id %q: %w", p.ID, err),
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
redirectPath := fmt.Sprintf("posts/%s?edit", p.ID)
|
||||
|
||||
a.executeRedirectTpl(rw, r, redirectPath)
|
||||
|
@ -48,9 +48,10 @@ type StoredPost struct {
|
||||
// Store is used for storing posts to a persistent storage.
|
||||
type Store interface {
|
||||
|
||||
// Set sets the Post data into the storage, keyed by the Post's ID. It
|
||||
// overwrites a previous Post with the same ID, if there was one.
|
||||
Set(post Post, now time.Time) error
|
||||
// Set sets the Post data into the storage, keyed by the Post's ID. If there
|
||||
// was not a previously existing Post with the same ID then Set returns
|
||||
// true. It overwrites the previous Post with the same ID otherwise.
|
||||
Set(post Post, now time.Time) (bool, error)
|
||||
|
||||
// Get returns count StoredPosts, sorted time descending, offset by the
|
||||
// given page number. The returned boolean indicates if there are more pages
|
||||
@ -114,13 +115,15 @@ func (s *store) withTx(cb func(*sql.Tx) error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *store) Set(post Post, now time.Time) error {
|
||||
func (s *store) Set(post Post, now time.Time) (bool, error) {
|
||||
|
||||
if post.ID == "" {
|
||||
return errors.New("post ID can't be empty")
|
||||
return false, errors.New("post ID can't be empty")
|
||||
}
|
||||
|
||||
return s.withTx(func(tx *sql.Tx) error {
|
||||
var first bool
|
||||
|
||||
err := s.withTx(func(tx *sql.Tx) error {
|
||||
|
||||
nowTS := now.Unix()
|
||||
|
||||
@ -173,8 +176,17 @@ func (s *store) Set(post Post, now time.Time) error {
|
||||
}
|
||||
}
|
||||
|
||||
err = tx.QueryRow(
|
||||
`SELECT 1 FROM posts WHERE id=? AND last_updated_at IS NULL`,
|
||||
post.ID,
|
||||
).Scan(new(int))
|
||||
|
||||
first = !errors.Is(err, sql.ErrNoRows)
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return first, err
|
||||
}
|
||||
|
||||
func (s *store) get(
|
||||
|
@ -108,7 +108,9 @@ func TestStore(t *testing.T) {
|
||||
post := testPost(0)
|
||||
post.Tags = []string{"foo", "bar"}
|
||||
|
||||
assert.NoError(t, h.store.Set(post, now))
|
||||
first, err := h.store.Set(post, now)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, first)
|
||||
|
||||
gotPost, err := h.store.GetByID(post.ID)
|
||||
assert.NoError(t, err)
|
||||
@ -129,7 +131,9 @@ func TestStore(t *testing.T) {
|
||||
post.Body = "anything"
|
||||
post.Tags = []string{"bar", "baz"}
|
||||
|
||||
assert.NoError(t, h.store.Set(post, newNow))
|
||||
first, err = h.store.Set(post, newNow)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, first)
|
||||
|
||||
gotPost, err = h.store.GetByID(post.ID)
|
||||
assert.NoError(t, err)
|
||||
@ -160,7 +164,8 @@ func TestStore(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, post := range posts {
|
||||
assert.NoError(t, h.store.Set(post.Post, now))
|
||||
_, err := h.store.Set(post.Post, now)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
gotPosts, hasMore, err := h.store.Get(0, 2)
|
||||
@ -174,7 +179,8 @@ func TestStore(t *testing.T) {
|
||||
assertPostsEqual(t, posts[2:4], gotPosts)
|
||||
|
||||
posts = append([]StoredPost{h.testStoredPost(4)}, posts...)
|
||||
assert.NoError(t, h.store.Set(posts[0].Post, now))
|
||||
_, err = h.store.Set(posts[0].Post, now)
|
||||
assert.NoError(t, err)
|
||||
|
||||
gotPosts, hasMore, err = h.store.Get(1, 2)
|
||||
assert.NoError(t, err)
|
||||
@ -204,7 +210,8 @@ func TestStore(t *testing.T) {
|
||||
posts[2].Series = "bar"
|
||||
|
||||
for _, post := range posts {
|
||||
assert.NoError(t, h.store.Set(post.Post, now))
|
||||
_, err := h.store.Set(post.Post, now)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
fooPosts, err := h.store.GetBySeries("foo")
|
||||
@ -238,7 +245,8 @@ func TestStore(t *testing.T) {
|
||||
posts[2].Tags = []string{"bar"}
|
||||
|
||||
for _, post := range posts {
|
||||
assert.NoError(t, h.store.Set(post.Post, now))
|
||||
_, err := h.store.Set(post.Post, now)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
fooPosts, err := h.store.GetByTag("foo")
|
||||
|
Loading…
Reference in New Issue
Block a user