|
|
|
@ -2,6 +2,7 @@ package http |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"bytes" |
|
|
|
|
"context" |
|
|
|
|
"errors" |
|
|
|
|
"fmt" |
|
|
|
|
"html/template" |
|
|
|
@ -16,6 +17,7 @@ import ( |
|
|
|
|
"github.com/gomarkdown/markdown/parser" |
|
|
|
|
"github.com/mediocregopher/blog.mediocregopher.com/srv/http/apiutil" |
|
|
|
|
"github.com/mediocregopher/blog.mediocregopher.com/srv/post" |
|
|
|
|
"github.com/mediocregopher/mediocre-go-lib/v2/mctx" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
func (a *api) parsePostBody(post post.Post) (*txttpl.Template, error) { |
|
|
|
@ -248,6 +250,10 @@ func (a *api) renderEditPostHandler(isDraft bool) http.Handler { |
|
|
|
|
) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} else if !isDraft { |
|
|
|
|
http.Error(rw, "Post ID required in URL", 400) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tags, err := a.params.PostStore.GetTags() |
|
|
|
@ -296,49 +302,54 @@ func postFromPostReq(r *http.Request) (post.Post, error) { |
|
|
|
|
return p, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (a *api) postPostHandler(isDraft bool) http.Handler { |
|
|
|
|
func (a *api) storeAndPublishPost(ctx context.Context, p post.Post) error { |
|
|
|
|
|
|
|
|
|
first, err := a.params.PostStore.Set(p, time.Now()) |
|
|
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
return fmt.Errorf("storing post with id %q: %w", p.ID, err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if !first { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
a.params.Logger.Info(ctx, "publishing blog post to mailing list") |
|
|
|
|
urlStr := a.postURL(p.ID, true) |
|
|
|
|
|
|
|
|
|
if err := a.params.MailingList.Publish(p.Title, urlStr); err != nil { |
|
|
|
|
return fmt.Errorf("publishing post to mailing list: %w", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if err := a.params.PostDraftStore.Delete(p.ID); err != nil { |
|
|
|
|
return fmt.Errorf("deleting draft: %w", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (a *api) postPostHandler() http.Handler { |
|
|
|
|
|
|
|
|
|
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { |
|
|
|
|
|
|
|
|
|
ctx := r.Context() |
|
|
|
|
|
|
|
|
|
p, err := postFromPostReq(r) |
|
|
|
|
if err != nil { |
|
|
|
|
apiutil.BadRequest(rw, r, err) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var first bool |
|
|
|
|
ctx = mctx.Annotate(ctx, "postID", p.ID) |
|
|
|
|
|
|
|
|
|
if isDraft { |
|
|
|
|
err = a.params.PostDraftStore.Set(p) |
|
|
|
|
} else { |
|
|
|
|
first, err = a.params.PostStore.Set(p, time.Now()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
if err := a.storeAndPublishPost(ctx, p); err != nil { |
|
|
|
|
apiutil.InternalServerError( |
|
|
|
|
rw, r, fmt.Errorf("storing post with id %q: %w", p.ID, err), |
|
|
|
|
rw, r, fmt.Errorf("storing/publishing post with id %q: %w", p.ID, err), |
|
|
|
|
) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if !isDraft && first { |
|
|
|
|
|
|
|
|
|
a.params.Logger.Info(r.Context(), "publishing blog post to mailing list") |
|
|
|
|
urlStr := a.postURL(p.ID, true) |
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if isDraft { |
|
|
|
|
a.executeRedirectTpl(rw, r, a.draftURL(p.ID, false)+"?edit") |
|
|
|
|
} else { |
|
|
|
|
a.executeRedirectTpl(rw, r, a.postURL(p.ID, false)+"?edit") |
|
|
|
|
} |
|
|
|
|
a.executeRedirectTpl(rw, r, a.postURL(p.ID, false)) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|