RSS replies to a user #111 (#145)

* add rss feed for replies to user

* fix add consts
This commit is contained in:
Anton Kosourov
2018-07-08 23:12:50 -05:00
committed by Umputun
parent 43092bb644
commit 75249bd7fe
2 changed files with 128 additions and 0 deletions
+51
View File
@@ -15,6 +15,8 @@ import (
)
const maxRssItems = 20
const maxLastForReply = 100
const maxReplyMins = 30 * time.Minute
// ui uses links like <post-url>#remark42__comment-<comment-id>
const uiNav = "#remark42__comment-"
@@ -23,6 +25,7 @@ func (s *Rest) rssRoutes() chi.Router {
router := chi.NewRouter()
router.Get("/post", s.rssPostCommentsCtrl)
router.Get("/site", s.rssSiteCommentsCtrl)
router.Get("/reply", s.rssRepliesCtrl)
return router
}
@@ -88,6 +91,54 @@ func (s *Rest) rssSiteCommentsCtrl(w http.ResponseWriter, r *http.Request) {
}
}
// GET /rss/reply?user=userID&site=siteID
func (s *Rest) rssRepliesCtrl(w http.ResponseWriter, r *http.Request) {
userID := r.URL.Query().Get("user")
siteID := r.URL.Query().Get("site")
log.Printf("[DEBUG] get rss replies to user %s for site %s", userID, siteID)
data, err := s.Cache.Get(cache.Key(cache.URLKey(r), siteID, userID), func() ([]byte, error) {
comments, e := s.DataService.Last(siteID, maxLastForReply)
if e != nil {
return nil, e
}
comments = s.adminService.alterComments(comments, r)
replies := []store.Comment{}
for _, c := range comments {
if len(replies) > maxRssItems || c.Timestamp.Add(maxReplyMins).Before(time.Now()) {
break
}
if c.ParentID != "" && !c.Deleted && c.User.ID != userID { // not interested replies to yourself
pc, errP := s.DataService.Get(c.Locator, c.ParentID)
if errP != nil {
return nil, errP
}
if pc.User.ID == userID {
replies = append(replies, c)
}
}
}
rss, e := s.toRssFeed(siteID, replies)
if e != nil {
return nil, e
}
return []byte(rss), e
})
if err != nil {
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't get replies")
return
}
w.Header().Set("Content-Type", "application/xml; charset=utf-8")
w.WriteHeader(http.StatusOK)
if _, err := w.Write(data); err != nil {
log.Printf("[WARN] failed to send response to %s, %s", r.RemoteAddr, err)
}
}
func (s *Rest) toRssFeed(url string, comments []store.Comment) (string, error) {
lastCommentTS := time.Unix(0, 0)
+77
View File
@@ -158,6 +158,83 @@ func TestServer_RssWithReply(t *testing.T) {
assert.Equal(t, expected, res)
}
func TestServer_RssReplies(t *testing.T) {
srv, ts := prep(t)
assert.NotNil(t, srv)
defer cleanup(ts)
waitOnSecChange()
pubDate := time.Now().Format(time.RFC1123Z)
c1 := store.Comment{
Text: "c1",
Locator: store.Locator{URL: "https://radio-t.com/blah1", SiteID: "radio-t"},
User: store.User{ID: "user1", Name: "user1"},
}
id1, err := srv.DataService.Create(c1)
assert.Nil(t, err)
c2 := store.Comment{
Text: "reply to c1 from user2",
ParentID: id1,
Locator: store.Locator{URL: "https://radio-t.com/blah1", SiteID: "radio-t"},
User: store.User{ID: "user2", Name: "user2"},
}
id2, err := srv.DataService.Create(c2)
assert.Nil(t, err)
c3 := store.Comment{
Text: "reply to c1 from user3",
ParentID: id1,
Locator: store.Locator{URL: "https://radio-t.com/blah1", SiteID: "radio-t"},
User: store.User{ID: "user3", Name: "user3"},
}
id3, err := srv.DataService.Create(c3)
assert.Nil(t, err)
c4 := store.Comment{
Text: "reply to c2 from developer one",
ParentID: id2,
Locator: store.Locator{URL: "https://radio-t.com/blah1", SiteID: "radio-t"},
}
addComment(t, c4, ts)
c5 := store.Comment{
Text: "developer one",
Locator: store.Locator{URL: "https://radio-t.com/blah1", SiteID: "radio-t"},
}
addComment(t, c5, ts)
// replies to c1 (user1). Must be [c3, c2]
res, code := get(t, ts.URL+"/api/v1/rss/reply?user=user1&site=radio-t")
assert.Equal(t, 200, code)
t.Log(res)
expected := fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>Remark42 comments</title>
<link>radio-t</link>
<description>comment updates</description>
<pubDate>%s</pubDate>
<item>
<title>user3 &gt; user1</title>
<link>https://radio-t.com/blah1#remark42__comment-%s</link>
<description>reply to c1 from user3</description>
<author>user3</author>
<pubDate>%s</pubDate>
</item>
<item>
<title>user2 &gt; user1</title>
<link>https://radio-t.com/blah1#remark42__comment-%s</link>
<description>reply to c1 from user2</description>
<author>user2</author>
<pubDate>%s</pubDate>
</item>
</channel>
</rss>`, pubDate, id3, pubDate, id2, pubDate)
expected, res = cleanRssFormatting(expected, res)
assert.Equal(t, expected, res)
_, code = get(t, ts.URL+"/api/v1/rss/reply?user=user1&site=radio-t-bad")
assert.Equal(t, 400, code)
}
func waitOnSecChange() {
for {
if time.Now().Nanosecond() < 100000000 {