Support micropub post visibility

This commit is contained in:
Jan-Lukas Else 2021-07-14 18:50:24 +02:00
parent 9e6a5fd90b
commit b82a6c59e8
2 changed files with 156 additions and 73 deletions

View File

@ -150,14 +150,24 @@ func (a *goBlog) micropubParseValuePostParamsValueMap(entry *post, values map[st
entry.Updated = updated[0] entry.Updated = updated[0]
delete(values, "updated") delete(values, "updated")
} }
if status, ok := values["post-status"]; ok && len(status) > 0 {
entry.Status = postStatus(status[0])
delete(values, "post-status")
}
if slug, ok := values["mp-slug"]; ok && len(slug) > 0 { if slug, ok := values["mp-slug"]; ok && len(slug) > 0 {
entry.Slug = slug[0] entry.Slug = slug[0]
delete(values, "mp-slug") delete(values, "mp-slug")
} }
// Status
statusStr := ""
if status, ok := values["post-status"]; ok && len(status) > 0 {
statusStr = status[0]
delete(values, "post-status")
}
visibilityStr := ""
if visibility, ok := values["visibility"]; ok && len(visibility) > 0 {
visibilityStr = visibility[0]
delete(values, "visibility")
}
if finalStatus := micropubStatus(statusNil, statusStr, visibilityStr); finalStatus != statusNil {
entry.Status = finalStatus
}
// Parameter // Parameter
if name, ok := values["name"]; ok { if name, ok := values["name"]; ok {
entry.Parameters["title"] = name entry.Parameters["title"] = name
@ -235,6 +245,7 @@ type microformatProperties struct {
Published []string `json:"published,omitempty"` Published []string `json:"published,omitempty"`
Updated []string `json:"updated,omitempty"` Updated []string `json:"updated,omitempty"`
PostStatus []string `json:"post-status,omitempty"` PostStatus []string `json:"post-status,omitempty"`
Visibility []string `json:"visibility,omitempty"`
Category []string `json:"category,omitempty"` Category []string `json:"category,omitempty"`
Content []string `json:"content,omitempty"` Content []string `json:"content,omitempty"`
URL []string `json:"url,omitempty"` URL []string `json:"url,omitempty"`
@ -264,12 +275,21 @@ func (a *goBlog) micropubParsePostParamsMfItem(entry *post, mf *microformatItem)
if len(mf.Properties.Updated) > 0 { if len(mf.Properties.Updated) > 0 {
entry.Updated = mf.Properties.Updated[0] entry.Updated = mf.Properties.Updated[0]
} }
if len(mf.Properties.PostStatus) > 0 {
entry.Status = postStatus(mf.Properties.PostStatus[0])
}
if len(mf.Properties.MpSlug) > 0 { if len(mf.Properties.MpSlug) > 0 {
entry.Slug = mf.Properties.MpSlug[0] entry.Slug = mf.Properties.MpSlug[0]
} }
// Status
status := ""
if len(mf.Properties.PostStatus) > 0 {
status = mf.Properties.PostStatus[0]
}
visibility := ""
if len(mf.Properties.Visibility) > 0 {
visibility = mf.Properties.Visibility[0]
}
if finalStatus := micropubStatus(statusNil, status, visibility); finalStatus != statusNil {
entry.Status = finalStatus
}
// Parameter // Parameter
if len(mf.Properties.Name) > 0 { if len(mf.Properties.Name) > 0 {
entry.Parameters["title"] = mf.Properties.Name entry.Parameters["title"] = mf.Properties.Name
@ -457,63 +477,100 @@ func (a *goBlog) micropubUpdate(w http.ResponseWriter, r *http.Request, u string
} }
oldPath := p.Path oldPath := p.Path
oldStatus := p.Status oldStatus := p.Status
if mf.Replace != nil { a.micropubUpdateReplace(p, mf.Replace)
for key, value := range mf.Replace { a.micropubUpdateAdd(p, mf.Add)
switch key { a.micropubUpdateDelete(p, mf.Delete)
case "content": err = a.computeExtraPostParameters(p)
p.Content = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) if err != nil {
case "published": a.serveError(w, r, err.Error(), http.StatusInternalServerError)
p.Published = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) return
case "updated": }
p.Updated = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) err = a.replacePost(p, oldPath, oldStatus)
case "name": if err != nil {
p.Parameters["title"] = cast.ToStringSlice(value) a.serveError(w, r, err.Error(), http.StatusInternalServerError)
case "category": return
p.Parameters[a.cfg.Micropub.CategoryParam] = cast.ToStringSlice(value) }
case "in-reply-to": http.Redirect(w, r, a.fullPostURL(p), http.StatusNoContent)
p.Parameters[a.cfg.Micropub.ReplyParam] = cast.ToStringSlice(value) }
case "like-of":
p.Parameters[a.cfg.Micropub.LikeParam] = cast.ToStringSlice(value) func (a *goBlog) micropubUpdateReplace(p *post, replace map[string][]interface{}) {
case "bookmark-of": if content, ok := replace["content"]; ok && len(content) > 0 {
p.Parameters[a.cfg.Micropub.BookmarkParam] = cast.ToStringSlice(value) p.Content = cast.ToStringSlice(content)[0]
case "audio": }
p.Parameters[a.cfg.Micropub.AudioParam] = cast.ToStringSlice(value) if published, ok := replace["published"]; ok && len(published) > 0 {
// TODO: photo p.Published = cast.ToStringSlice(published)[0]
}
if updated, ok := replace["updated"]; ok && len(updated) > 0 {
p.Updated = cast.ToStringSlice(updated)[0]
}
// Status
statusStr := ""
if status, ok := replace["post-status"]; ok && len(status) > 0 {
statusStr = cast.ToStringSlice(status)[0]
}
visibilityStr := ""
if visibility, ok := replace["visibility"]; ok && len(visibility) > 0 {
visibilityStr = cast.ToStringSlice(visibility)[0]
}
if finalStatus := micropubStatus(p.Status, statusStr, visibilityStr); finalStatus != statusNil {
p.Status = finalStatus
}
// Parameters
if name, ok := replace["name"]; ok && name != nil {
p.Parameters["title"] = cast.ToStringSlice(name)
}
if category, ok := replace["category"]; ok && category != nil {
p.Parameters[a.cfg.Micropub.CategoryParam] = cast.ToStringSlice(category)
}
if reply, ok := replace["in-reply-to"]; ok && reply != nil {
p.Parameters[a.cfg.Micropub.ReplyParam] = cast.ToStringSlice(reply)
}
if like, ok := replace["like-of"]; ok && like != nil {
p.Parameters[a.cfg.Micropub.LikeParam] = cast.ToStringSlice(like)
}
if bookmark, ok := replace["bookmark-of"]; ok && bookmark != nil {
p.Parameters[a.cfg.Micropub.BookmarkParam] = cast.ToStringSlice(bookmark)
}
if audio, ok := replace["audio"]; ok && audio != nil {
p.Parameters[a.cfg.Micropub.AudioParam] = cast.ToStringSlice(audio)
}
// TODO: photos
}
func (a *goBlog) micropubUpdateAdd(p *post, add map[string][]interface{}) {
for key, value := range add {
switch key {
case "content":
p.Content += strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " "))
case "published":
p.Published = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " "))
case "updated":
p.Updated = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " "))
case "category":
category := p.Parameters[a.cfg.Micropub.CategoryParam]
if category == nil {
category = []string{}
} }
p.Parameters[a.cfg.Micropub.CategoryParam] = append(category, cast.ToStringSlice(value)...)
case "in-reply-to":
p.Parameters[a.cfg.Micropub.ReplyParam] = cast.ToStringSlice(value)
case "like-of":
p.Parameters[a.cfg.Micropub.LikeParam] = cast.ToStringSlice(value)
case "bookmark-of":
p.Parameters[a.cfg.Micropub.BookmarkParam] = cast.ToStringSlice(value)
case "audio":
audio := p.Parameters[a.cfg.Micropub.CategoryParam]
if audio == nil {
audio = []string{}
}
p.Parameters[a.cfg.Micropub.AudioParam] = append(audio, cast.ToStringSlice(value)...)
// TODO: photo
} }
} }
if mf.Add != nil { }
for key, value := range mf.Add {
switch key { func (a *goBlog) micropubUpdateDelete(p *post, del interface{}) {
case "content": if del != nil {
p.Content += strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " "))
case "published":
p.Published = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " "))
case "updated":
p.Updated = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " "))
case "category":
category := p.Parameters[a.cfg.Micropub.CategoryParam]
if category == nil {
category = []string{}
}
p.Parameters[a.cfg.Micropub.CategoryParam] = append(category, cast.ToStringSlice(value)...)
case "in-reply-to":
p.Parameters[a.cfg.Micropub.ReplyParam] = cast.ToStringSlice(value)
case "like-of":
p.Parameters[a.cfg.Micropub.LikeParam] = cast.ToStringSlice(value)
case "bookmark-of":
p.Parameters[a.cfg.Micropub.BookmarkParam] = cast.ToStringSlice(value)
case "audio":
audio := p.Parameters[a.cfg.Micropub.CategoryParam]
if audio == nil {
audio = []string{}
}
p.Parameters[a.cfg.Micropub.AudioParam] = append(audio, cast.ToStringSlice(value)...)
// TODO: photo
}
}
}
if del := mf.Delete; del != nil {
if reflect.TypeOf(del).Kind() == reflect.Slice { if reflect.TypeOf(del).Kind() == reflect.Slice {
toDelete, ok := del.([]interface{}) toDelete, ok := del.([]interface{})
if ok { if ok {
@ -566,15 +623,26 @@ func (a *goBlog) micropubUpdate(w http.ResponseWriter, r *http.Request, u string
} }
} }
} }
err = a.computeExtraPostParameters(p) }
if err != nil {
a.serveError(w, r, err.Error(), http.StatusInternalServerError) func micropubStatus(defaultStatus postStatus, status string, visibility string) (final postStatus) {
return final = defaultStatus
} switch status {
err = a.replacePost(p, oldPath, oldStatus) case "published":
if err != nil { final = statusPublished
a.serveError(w, r, err.Error(), http.StatusInternalServerError) case "draft":
return final = statusDraft
} }
http.Redirect(w, r, a.fullPostURL(p), http.StatusNoContent) if final != statusDraft {
// Only override status if it's not a draft
switch visibility {
case "public":
final = statusPublished
case "unlisted":
final = statusUnlisted
case "private":
final = statusPrivate
}
}
return final
} }

View File

@ -137,13 +137,28 @@ func (a *goBlog) postToMfItem(p *post) *microformatItem {
params["priority"] = p.Priority params["priority"] = p.Priority
pb, _ := yaml.Marshal(params) pb, _ := yaml.Marshal(params)
content := fmt.Sprintf("---\n%s---\n%s", string(pb), p.Content) content := fmt.Sprintf("---\n%s---\n%s", string(pb), p.Content)
var mfStatus, mfVisibility string
switch p.Status {
case statusDraft:
mfStatus = "draft"
case statusPublished:
mfStatus = "published"
mfVisibility = "public"
case statusUnlisted:
mfStatus = "published"
mfVisibility = "unlisted"
case statusPrivate:
mfStatus = "published"
mfVisibility = "private"
}
return &microformatItem{ return &microformatItem{
Type: []string{"h-entry"}, Type: []string{"h-entry"},
Properties: &microformatProperties{ Properties: &microformatProperties{
Name: p.Parameters["title"], Name: p.Parameters["title"],
Published: []string{p.Published}, Published: []string{p.Published},
Updated: []string{p.Updated}, Updated: []string{p.Updated},
PostStatus: []string{string(p.Status)}, PostStatus: []string{mfStatus},
Visibility: []string{mfVisibility},
Category: p.Parameters[a.cfg.Micropub.CategoryParam], Category: p.Parameters[a.cfg.Micropub.CategoryParam],
Content: []string{content}, Content: []string{content},
URL: []string{a.fullPostURL(p)}, URL: []string{a.fullPostURL(p)},