From ff7828c55827cc69b5a2a698a4a119075b6f5a9e Mon Sep 17 00:00:00 2001 From: Matt Baer Date: Wed, 7 Aug 2019 09:26:07 -0400 Subject: [PATCH] Link hashtags to Reader when Chorus mode enabled instead of linking to posts only on a user's blog. Ref T681 --- activitypub.go | 8 ++++---- app.go | 6 +++--- collections.go | 6 +++--- database.go | 13 +++++++------ export.go | 2 +- feed.go | 6 +++--- postrender.go | 23 ++++++++++++++--------- posts.go | 19 ++++++++++++------- read.go | 4 ++-- sitemap.go | 2 +- 10 files changed, 50 insertions(+), 39 deletions(-) diff --git a/activitypub.go b/activitypub.go index 997609d..e37fb97 100644 --- a/activitypub.go +++ b/activitypub.go @@ -129,10 +129,10 @@ func handleFetchCollectionOutbox(app *App, w http.ResponseWriter, r *http.Reques ocp := activitystreams.NewOrderedCollectionPage(accountRoot, "outbox", res.TotalPosts, p) ocp.OrderedItems = []interface{}{} - posts, err := app.db.GetPosts(c, p, false, true, false) + posts, err := app.db.GetPosts(app.cfg, c, p, false, true, false) for _, pp := range *posts { pp.Collection = res - o := pp.ActivityObject() + o := pp.ActivityObject(app.cfg) a := activitystreams.NewCreateActivity(o) ocp.OrderedItems = append(ocp.OrderedItems, *a) } @@ -524,7 +524,7 @@ func deleteFederatedPost(app *App, p *PublicPost, collID int64) error { } p.Collection.hostName = app.cfg.App.Host actor := p.Collection.PersonObject(collID) - na := p.ActivityObject() + na := p.ActivityObject(app.cfg) // Add followers p.Collection.ID = collID @@ -570,7 +570,7 @@ func federatePost(app *App, p *PublicPost, collID int64, isUpdate bool) error { } } actor := p.Collection.PersonObject(collID) - na := p.ActivityObject() + na := p.ActivityObject(app.cfg) // Add followers p.Collection.ID = collID diff --git a/app.go b/app.go index 68ba7c7..9525a07 100644 --- a/app.go +++ b/app.go @@ -224,14 +224,14 @@ func handleViewHome(app *App, w http.ResponseWriter, r *http.Request) error { log.Error("unable to get landing banner: %v", err) return impart.HTTPError{http.StatusInternalServerError, fmt.Sprintf("Could not get banner: %v", err)} } - p.Banner = template.HTML(applyMarkdown([]byte(banner.Content), "")) + p.Banner = template.HTML(applyMarkdown([]byte(banner.Content), "", app.cfg)) content, err := getLandingBody(app) if err != nil { log.Error("unable to get landing content: %v", err) return impart.HTTPError{http.StatusInternalServerError, fmt.Sprintf("Could not get content: %v", err)} } - p.Content = template.HTML(applyMarkdown([]byte(content.Content), "")) + p.Content = template.HTML(applyMarkdown([]byte(content.Content), "", app.cfg)) // Get error messages session, err := app.sessionStore.Get(r, cookieName) @@ -279,7 +279,7 @@ func handleTemplatedPage(app *App, w http.ResponseWriter, r *http.Request, t *te return err } p.ContentTitle = c.Title.String - p.Content = template.HTML(applyMarkdown([]byte(c.Content), "")) + p.Content = template.HTML(applyMarkdown([]byte(c.Content), "", app.cfg)) p.PlainContent = shortPostDescription(stripmd.Strip(c.Content)) if !c.Updated.IsZero() { p.Updated = c.Updated.Format("January 2, 2006") diff --git a/collections.go b/collections.go index 0d2549a..b8454e1 100644 --- a/collections.go +++ b/collections.go @@ -496,7 +496,7 @@ func fetchCollectionPosts(app *App, w http.ResponseWriter, r *http.Request) erro } } - posts, err := app.db.GetPosts(c, page, isCollOwner, false, false) + posts, err := app.db.GetPosts(app.cfg, c, page, isCollOwner, false, false) if err != nil { return err } @@ -730,7 +730,7 @@ func handleViewCollection(app *App, w http.ResponseWriter, r *http.Request) erro return impart.HTTPError{http.StatusFound, redirURL} } - coll.Posts, _ = app.db.GetPosts(c, page, cr.isCollOwner, false, false) + coll.Posts, _ = app.db.GetPosts(app.cfg, c, page, cr.isCollOwner, false, false) // Serve collection displayPage := CollectionPage{ @@ -825,7 +825,7 @@ func handleViewCollectionTag(app *App, w http.ResponseWriter, r *http.Request) e coll := newDisplayCollection(c, cr, page) - coll.Posts, _ = app.db.GetPostsTagged(c, tag, page, cr.isCollOwner) + coll.Posts, _ = app.db.GetPostsTagged(app.cfg, c, tag, page, cr.isCollOwner) if coll.Posts != nil && len(*coll.Posts) == 0 { return ErrCollectionPageNotFound } diff --git a/database.go b/database.go index 1ea9872..9d4891d 100644 --- a/database.go +++ b/database.go @@ -29,6 +29,7 @@ import ( "github.com/writeas/web-core/log" "github.com/writeas/web-core/query" "github.com/writeas/writefreely/author" + "github.com/writeas/writefreely/config" "github.com/writeas/writefreely/key" ) @@ -105,8 +106,8 @@ type writestore interface { ClaimPosts(userID int64, collAlias string, posts *[]ClaimPostRequest) (*[]ClaimPostResult, error) GetPostsCount(c *CollectionObj, includeFuture bool) - GetPosts(c *Collection, page int, includeFuture, forceRecentFirst, includePinned bool) (*[]PublicPost, error) - GetPostsTagged(c *Collection, tag string, page int, includeFuture bool) (*[]PublicPost, error) + GetPosts(cfg *config.Config, c *Collection, page int, includeFuture, forceRecentFirst, includePinned bool) (*[]PublicPost, error) + GetPostsTagged(cfg *config.Config, c *Collection, tag string, page int, includeFuture bool) (*[]PublicPost, error) GetAPFollowers(c *Collection) (*[]RemoteUser, error) GetAPActorKeys(collectionID int64) ([]byte, []byte) @@ -1067,7 +1068,7 @@ func (db *datastore) GetPostsCount(c *CollectionObj, includeFuture bool) { // It will return future posts if `includeFuture` is true. // It will include only standard (non-pinned) posts unless `includePinned` is true. // TODO: change includeFuture to isOwner, since that's how it's used -func (db *datastore) GetPosts(c *Collection, page int, includeFuture, forceRecentFirst, includePinned bool) (*[]PublicPost, error) { +func (db *datastore) GetPosts(cfg *config.Config, c *Collection, page int, includeFuture, forceRecentFirst, includePinned bool) (*[]PublicPost, error) { collID := c.ID cf := c.NewFormat() @@ -1112,7 +1113,7 @@ func (db *datastore) GetPosts(c *Collection, page int, includeFuture, forceRecen break } p.extractData() - p.formatContent(c, includeFuture) + p.formatContent(cfg, c, includeFuture) posts = append(posts, p.processPost()) } @@ -1128,7 +1129,7 @@ func (db *datastore) GetPosts(c *Collection, page int, includeFuture, forceRecen // given tag. // It will return future posts if `includeFuture` is true. // TODO: change includeFuture to isOwner, since that's how it's used -func (db *datastore) GetPostsTagged(c *Collection, tag string, page int, includeFuture bool) (*[]PublicPost, error) { +func (db *datastore) GetPostsTagged(cfg *config.Config, c *Collection, tag string, page int, includeFuture bool) (*[]PublicPost, error) { collID := c.ID cf := c.NewFormat() @@ -1176,7 +1177,7 @@ func (db *datastore) GetPostsTagged(c *Collection, tag string, page int, include break } p.extractData() - p.formatContent(c, includeFuture) + p.formatContent(cfg, c, includeFuture) posts = append(posts, p.processPost()) } diff --git a/export.go b/export.go index 47a2603..b30b59d 100644 --- a/export.go +++ b/export.go @@ -118,7 +118,7 @@ func compileFullExport(app *App, u *User) *ExportUser { var collObjs []CollectionObj for _, c := range *colls { co := &CollectionObj{Collection: c} - co.Posts, err = app.db.GetPosts(&c, 0, true, false, true) + co.Posts, err = app.db.GetPosts(app.cfg, &c, 0, true, false, true) if err != nil { log.Error("unable to get collection posts: %v", err) } diff --git a/feed.go b/feed.go index dd82c33..32feb82 100644 --- a/feed.go +++ b/feed.go @@ -55,9 +55,9 @@ func ViewFeed(app *App, w http.ResponseWriter, req *http.Request) error { tag := mux.Vars(req)["tag"] if tag != "" { - coll.Posts, _ = app.db.GetPostsTagged(c, tag, 1, false) + coll.Posts, _ = app.db.GetPostsTagged(app.cfg, c, tag, 1, false) } else { - coll.Posts, _ = app.db.GetPosts(c, 1, false, true, false) + coll.Posts, _ = app.db.GetPosts(app.cfg, c, 1, false, true, false) } author := "" @@ -94,7 +94,7 @@ func ViewFeed(app *App, w http.ResponseWriter, req *http.Request) error { Title: title, Link: &Link{Href: permalink}, Description: "", - Content: applyMarkdown([]byte(p.Content), ""), + Content: applyMarkdown([]byte(p.Content), "", app.cfg), Author: &Author{author, ""}, Created: p.Created, Updated: p.Updated, diff --git a/postrender.go b/postrender.go index af715be..193b979 100644 --- a/postrender.go +++ b/postrender.go @@ -16,6 +16,7 @@ import ( stripmd "github.com/writeas/go-strip-markdown" "github.com/writeas/saturday" "github.com/writeas/web-core/stringmanip" + "github.com/writeas/writefreely/config" "github.com/writeas/writefreely/parse" "html" "html/template" @@ -34,27 +35,27 @@ var ( markeddownReg = regexp.MustCompile("

(.+)

") ) -func (p *Post) formatContent(c *Collection, isOwner bool) { +func (p *Post) formatContent(cfg *config.Config, c *Collection, isOwner bool) { baseURL := c.CanonicalURL() if !isSingleUser { baseURL = "/" + c.Alias + "/" } p.HTMLTitle = template.HTML(applyBasicMarkdown([]byte(p.Title.String))) - p.HTMLContent = template.HTML(applyMarkdown([]byte(p.Content), baseURL)) + p.HTMLContent = template.HTML(applyMarkdown([]byte(p.Content), baseURL, cfg)) if exc := strings.Index(string(p.Content), ""); exc > -1 { - p.HTMLExcerpt = template.HTML(applyMarkdown([]byte(p.Content[:exc]), baseURL)) + p.HTMLExcerpt = template.HTML(applyMarkdown([]byte(p.Content[:exc]), baseURL, cfg)) } } -func (p *PublicPost) formatContent(isOwner bool) { - p.Post.formatContent(&p.Collection.Collection, isOwner) +func (p *PublicPost) formatContent(cfg *config.Config, isOwner bool) { + p.Post.formatContent(cfg, &p.Collection.Collection, isOwner) } -func applyMarkdown(data []byte, baseURL string) string { - return applyMarkdownSpecial(data, false, baseURL) +func applyMarkdown(data []byte, baseURL string, cfg *config.Config) string { + return applyMarkdownSpecial(data, false, baseURL, cfg) } -func applyMarkdownSpecial(data []byte, skipNoFollow bool, baseURL string) string { +func applyMarkdownSpecial(data []byte, skipNoFollow bool, baseURL string, cfg *config.Config) string { mdExtensions := 0 | blackfriday.EXTENSION_TABLES | blackfriday.EXTENSION_FENCED_CODE | @@ -74,7 +75,11 @@ func applyMarkdownSpecial(data []byte, skipNoFollow bool, baseURL string) string md := blackfriday.Markdown([]byte(data), blackfriday.HtmlRenderer(htmlFlags, "", ""), mdExtensions) if baseURL != "" { // Replace special text generated by Markdown parser - md = []byte(hashtagReg.ReplaceAll(md, []byte("#$1"))) + tagPrefix := baseURL + "tag:" + if cfg.App.Chorus { + tagPrefix = "/read/t/" + } + md = []byte(hashtagReg.ReplaceAll(md, []byte("#$1"))) } // Strip out bad HTML policy := getSanitizationPolicy() diff --git a/posts.go b/posts.go index b1ce20f..5a5c100 100644 --- a/posts.go +++ b/posts.go @@ -35,6 +35,7 @@ import ( "github.com/writeas/web-core/i18n" "github.com/writeas/web-core/log" "github.com/writeas/web-core/tags" + "github.com/writeas/writefreely/config" "github.com/writeas/writefreely/page" "github.com/writeas/writefreely/parse" ) @@ -376,7 +377,7 @@ func handleViewPost(app *App, w http.ResponseWriter, r *http.Request) error { Direction: d, } if !isRaw { - post.HTMLContent = template.HTML(applyMarkdown([]byte(content), "")) + post.HTMLContent = template.HTML(applyMarkdown([]byte(content), "", app.cfg)) } } @@ -1032,7 +1033,7 @@ func fetchPost(app *App, w http.ResponseWriter, r *http.Request) error { } p.Collection = &CollectionObj{Collection: *coll} - po := p.ActivityObject() + po := p.ActivityObject(app.cfg) po.Context = []interface{}{activitystreams.Namespace} return impart.RenderActivityJSON(w, po, http.StatusOK) } @@ -1067,7 +1068,7 @@ func (p *PublicPost) CanonicalURL() string { return p.Collection.CanonicalURL() + p.Slug.String } -func (p *PublicPost) ActivityObject() *activitystreams.Object { +func (p *PublicPost) ActivityObject(cfg *config.Config) *activitystreams.Object { o := activitystreams.NewArticleObject() o.ID = p.Collection.FederatedAPIBase() + "api/posts/" + p.ID o.Published = p.Created @@ -1078,7 +1079,7 @@ func (p *PublicPost) ActivityObject() *activitystreams.Object { } o.Name = p.DisplayTitle() if p.HTMLContent == template.HTML("") { - p.formatContent(false) + p.formatContent(cfg, false) } o.Content = string(p.HTMLContent) if p.Language.Valid { @@ -1093,7 +1094,11 @@ func (p *PublicPost) ActivityObject() *activitystreams.Object { if isSingleUser { tagBaseURL = p.Collection.CanonicalURL() + "tag:" } else { - tagBaseURL = fmt.Sprintf("%s/%s/tag:", p.Collection.hostName, p.Collection.Alias) + if cfg.App.Chorus { + tagBaseURL = fmt.Sprintf("%s/read/t/", p.Collection.hostName) + } else { + tagBaseURL = fmt.Sprintf("%s/%s/tag:", p.Collection.hostName, p.Collection.Alias) + } } for _, t := range p.Tags { o.Tag = append(o.Tag, activitystreams.Tag{ @@ -1330,14 +1335,14 @@ func viewCollectionPost(app *App, w http.ResponseWriter, r *http.Request) error fmt.Fprint(w, p.Content) } else if strings.Contains(r.Header.Get("Accept"), "application/activity+json") { p.extractData() - ap := p.ActivityObject() + ap := p.ActivityObject(app.cfg) ap.Context = []interface{}{activitystreams.Namespace} return impart.RenderActivityJSON(w, ap, http.StatusOK) } else { p.extractData() p.Content = strings.Replace(p.Content, "", "", 1) // TODO: move this to function - p.formatContent(cr.isCollOwner) + p.formatContent(app.cfg, cr.isCollOwner) tp := struct { *PublicPost page.StaticPage diff --git a/read.go b/read.go index fa350fa..3efb89d 100644 --- a/read.go +++ b/read.go @@ -100,7 +100,7 @@ func (app *App) FetchPublicPosts() (interface{}, error) { } p.extractData() - p.HTMLContent = template.HTML(applyMarkdown([]byte(p.Content), "")) + p.HTMLContent = template.HTML(applyMarkdown([]byte(p.Content), "", app.cfg)) fp := p.processPost() if isCollectionPost { fp.Collection = &CollectionObj{Collection: *c} @@ -295,7 +295,7 @@ func viewLocalTimelineFeed(app *App, w http.ResponseWriter, req *http.Request) e Title: title, Link: &Link{Href: permalink}, Description: "", - Content: applyMarkdown([]byte(p.Content), ""), + Content: applyMarkdown([]byte(p.Content), "", app.cfg), Author: &Author{author, ""}, Created: p.Created, Updated: p.Updated, diff --git a/sitemap.go b/sitemap.go index 4dfd953..00e148f 100644 --- a/sitemap.go +++ b/sitemap.go @@ -66,7 +66,7 @@ func handleViewSitemap(app *App, w http.ResponseWriter, r *http.Request) error { host = c.CanonicalURL() sm := buildSitemap(host, pre) - posts, err := app.db.GetPosts(c, 0, false, false, false) + posts, err := app.db.GetPosts(app.cfg, c, 0, false, false, false) if err != nil { log.Error("Error getting posts: %v", err) return err