Support filtering blog posts by language

Ref T805
This commit is contained in:
Matt Baer 2021-09-13 18:36:36 -04:00
parent a122e4e98a
commit f4977c7a34
3 changed files with 153 additions and 0 deletions

View file

@ -28,6 +28,7 @@ import (
"github.com/writeas/web-core/activitystreams"
"github.com/writeas/web-core/auth"
"github.com/writeas/web-core/bots"
"github.com/writeas/web-core/i18n"
"github.com/writeas/web-core/log"
waposts "github.com/writeas/web-core/posts"
"github.com/writefreely/writefreely/author"
@ -366,6 +367,16 @@ func (c CollectionPage) DisplayMonetization() string {
return displayMonetization(c.Monetization, c.Alias)
}
func (c *DisplayCollection) Direction() string {
if c.Language == "" {
return "auto"
}
if i18n.LangIsRTL(c.Language) {
return "rtl"
}
return "ltr"
}
func newCollection(app *App, w http.ResponseWriter, r *http.Request) error {
reqJSON := IsJSON(r)
alias := r.FormValue("alias")
@ -991,6 +1002,92 @@ func handleViewCollectionTag(app *App, w http.ResponseWriter, r *http.Request) e
return nil
}
func handleViewCollectionLang(app *App, w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)
lang := vars["lang"]
cr := &collectionReq{}
err := processCollectionRequest(cr, vars, w, r)
if err != nil {
return err
}
u, err := checkUserForCollection(app, cr, r, false)
if err != nil {
return err
}
page := getCollectionPage(vars)
c, err := processCollectionPermissions(app, cr, u, w, r)
if c == nil || err != nil {
return err
}
coll := newDisplayCollection(c, cr, page)
coll.Language = lang
coll.Posts, _ = app.db.GetLangPosts(app.cfg, c, lang, page, cr.isCollOwner)
if err != nil {
return ErrCollectionPageNotFound
}
// Serve collection
displayPage := struct {
CollectionPage
Tag string
}{
CollectionPage: CollectionPage{
DisplayCollection: coll,
StaticPage: pageForReq(app, r),
IsCustomDomain: cr.isCustomDomain,
},
Tag: lang,
}
var owner *User
if u != nil {
displayPage.Username = u.Username
displayPage.IsOwner = u.ID == coll.OwnerID
if displayPage.IsOwner {
// Add in needed information for users viewing their own collection
owner = u
displayPage.CanPin = true
pubColls, err := app.db.GetPublishableCollections(owner, app.cfg.App.Host)
if err != nil {
log.Error("unable to fetch collections: %v", err)
}
displayPage.Collections = pubColls
}
}
isOwner := owner != nil
if !isOwner {
// Current user doesn't own collection; retrieve owner information
owner, err = app.db.GetUserByID(coll.OwnerID)
if err != nil {
// Log the error and just continue
log.Error("Error getting user for collection: %v", err)
}
if owner.IsSilenced() {
return ErrCollectionNotFound
}
}
displayPage.Silenced = owner != nil && owner.IsSilenced()
displayPage.Owner = owner
coll.Owner = displayPage.Owner
// Add more data
// TODO: fix this mess of collections inside collections
displayPage.PinnedPosts, _ = app.db.GetPinnedPosts(coll.CollectionObj, isOwner)
displayPage.Monetization = app.db.GetCollectionAttribute(coll.ID, "monetization_pointer")
err = templates["collection"].ExecuteTemplate(w, "collection", displayPage)
if err != nil {
log.Error("Unable to render collection lang page: %v", err)
}
return nil
}
func handleCollectionPostRedirect(app *App, w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)
slug := vars["slug"]

View file

@ -1260,6 +1260,61 @@ func (db *datastore) GetPostsTagged(cfg *config.Config, c *Collection, tag strin
return &posts, nil
}
func (db *datastore) GetLangPosts(cfg *config.Config, c *Collection, lang string, page int, includeFuture bool) (*[]PublicPost, error) {
collID := c.ID
cf := c.NewFormat()
order := "DESC"
if cf.Ascending() {
order = "ASC"
}
pagePosts := cf.PostsPerPage()
start := page*pagePosts - pagePosts
if page == 0 {
start = 0
pagePosts = 1000
}
limitStr := ""
if page > 0 {
limitStr = fmt.Sprintf(" LIMIT %d, %d", start, pagePosts)
}
timeCondition := ""
if !includeFuture {
timeCondition = "AND created <= " + db.now()
}
rows, err := db.Query("SELECT "+postCols+" FROM posts WHERE collection_id = ? AND language = ? "+timeCondition+" ORDER BY created "+order+limitStr, collID, lang)
if err != nil {
log.Error("Failed selecting from posts: %v", err)
return nil, impart.HTTPError{http.StatusInternalServerError, "Couldn't retrieve collection posts."}
}
defer rows.Close()
// TODO: extract this common row scanning logic for queries using `postCols`
posts := []PublicPost{}
for rows.Next() {
p := &Post{}
err = rows.Scan(&p.ID, &p.Slug, &p.Font, &p.Language, &p.RTL, &p.Privacy, &p.OwnerID, &p.CollectionID, &p.PinnedPosition, &p.Created, &p.Updated, &p.ViewCount, &p.Title, &p.Content)
if err != nil {
log.Error("Failed scanning row: %v", err)
break
}
p.extractData()
p.augmentContent(c)
p.formatContent(cfg, c, includeFuture, false)
posts = append(posts, p.processPost())
}
err = rows.Err()
if err != nil {
log.Error("Error after Next() on rows: %v", err)
}
return &posts, nil
}
func (db *datastore) GetAPFollowers(c *Collection) (*[]RemoteUser, error) {
rows, err := db.Query("SELECT actor_id, inbox, shared_inbox FROM remotefollows f INNER JOIN remoteusers u ON f.remote_user_id = u.id WHERE collection_id = ?", c.ID)
if err != nil {

View file

@ -216,6 +216,7 @@ func InitRoutes(apper Apper, r *mux.Router) *mux.Router {
func RouteCollections(handler *Handler, r *mux.Router) {
r.HandleFunc("/logout", handler.Web(handleLogOutCollection, UserLevelOptional))
r.HandleFunc("/page/{page:[0-9]+}", handler.Web(handleViewCollection, UserLevelReader))
r.HandleFunc("/lang:{lang}", handler.Web(handleViewCollectionLang, UserLevelOptional))
r.HandleFunc("/tag:{tag}", handler.Web(handleViewCollectionTag, UserLevelReader))
r.HandleFunc("/tag:{tag}/feed/", handler.Web(ViewFeed, UserLevelReader))
r.HandleFunc("/sitemap.xml", handler.AllReader(handleViewSitemap))