From e7dab7a2b4dfda05b63d9cc1096696b9ef025229 Mon Sep 17 00:00:00 2001 From: Umputun Date: Mon, 12 Mar 2018 00:39:14 -0500 Subject: [PATCH] notif simplified to be site-level --- app/main.go | 4 +++- app/notifier/notifier.go | 25 +++++++++++++------------ app/rest/api/rest.go | 27 +++++++++++++-------------- remark.rest | 2 +- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/app/main.go b/app/main.go index 3e91c06b..7acdad95 100644 --- a/app/main.go +++ b/app/main.go @@ -232,7 +232,9 @@ func postFlushFn() { log.Printf("[WARN] failed to refresh cached list for %s, %s", site, err) return } - _ = resp.Body.Close() + if err = resp.Body.Close(); err != nil { + log.Printf("[WARN] failed to close response body, %s", err) + } } } } diff --git a/app/notifier/notifier.go b/app/notifier/notifier.go index 1e0c753f..99f9eaec 100644 --- a/app/notifier/notifier.go +++ b/app/notifier/notifier.go @@ -1,3 +1,4 @@ +// Package notifier handles update notification as well as subscriptions to notification package notifier import ( @@ -10,10 +11,10 @@ import ( // Interface defines notifier, sending messages triggered by topic/reply updates type Interface interface { - Subscribe(locator store.Locator, user store.User) error - UnSubscribe(locator store.Locator, user store.User) error + Subscribe(user store.User) error + UnSubscribe(user store.User) error OnUpdate(comment store.Comment) error - Status(locator store.Locator, user store.User) (bool, error) + Status(user store.User) (bool, error) } // NoOperation implements Interface doing nothing but logging @@ -29,20 +30,20 @@ func NewNoOperation() *NoOperation { } // Subscribe is a fake, just logging attempt -func (n *NoOperation) Subscribe(locator store.Locator, user store.User) error { +func (n *NoOperation) Subscribe(user store.User) error { n.Lock() - n.status[n.key(locator, user)] = struct{}{} + n.status[user.ID] = struct{}{} n.Unlock() - log.Printf("[DEBUG] user %+v subscribed to %+v", user, locator) + log.Printf("[DEBUG] user %+v subscribed to updates", user) return nil } // UnSubscribe is a fake, just logging attempt -func (n *NoOperation) UnSubscribe(locator store.Locator, user store.User) error { +func (n *NoOperation) UnSubscribe(user store.User) error { n.Lock() - delete(n.status, n.key(locator, user)) + delete(n.status, user.ID) n.Unlock() - log.Printf("[DEBUG] user %+v unsubscribed from %+v", user, locator) + log.Printf("[DEBUG] user %+v unsubscribed from updates", user) return nil } @@ -52,11 +53,11 @@ func (n *NoOperation) OnUpdate(comment store.Comment) error { return nil } -// Status returns from in-memory -func (n *NoOperation) Status(locator store.Locator, user store.User) (bool, error) { +// Status returns from in-memory map +func (n *NoOperation) Status(user store.User) (bool, error) { n.RLock() defer n.RUnlock() - _, found := n.status[n.key(locator, user)] + _, found := n.status[user.ID] return found, nil } diff --git a/app/rest/api/rest.go b/app/rest/api/rest.go index 6f55bd73..e38f5e31 100644 --- a/app/rest/api/rest.go +++ b/app/rest/api/rest.go @@ -462,48 +462,47 @@ func (s *Rest) voteCtrl(w http.ResponseWriter, r *http.Request) { render.JSON(w, r, JSON{"id": comment.ID, "score": comment.Score}) } -// PUT /notify?site=siteID&url=post-url&action=1 - subscribe/unsubscribe to notification +// PUT /notify?site=siteID&action=1 - subscribe/unsubscribe to notification func (s *Rest) notifyActionCtrl(w http.ResponseWriter, r *http.Request) { user, err := rest.GetUserInfo(r) if err != nil { rest.SendErrorJSON(w, r, http.StatusUnauthorized, err, "can't get user info") return } - locator := store.Locator{SiteID: r.URL.Query().Get("site"), URL: r.URL.Query().Get("url")} action := "unknown" switch r.URL.Query().Get("action") { case "1": - err = s.Notifier.Subscribe(locator, user) + err = s.Notifier.Subscribe(user) action = "subscribe" case "0": - err = s.Notifier.UnSubscribe(locator, user) + err = s.Notifier.UnSubscribe(user) action = "unsubscribe" } if err != nil { - rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't subscribe/unsubscribe for notifications") + rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't subscribe/unsubscribe") return } - render.JSON(w, r, JSON{"locator": locator, "user": user.ID, "action": action}) + render.JSON(w, r, JSON{"user": user.ID, "action": action}) } -// GET /notify?site=siteID&url=post-url - get notification status +// GET /notify?site=siteID - get notification status for user func (s *Rest) notifyStatusCtrl(w http.ResponseWriter, r *http.Request) { user, err := rest.GetUserInfo(r) if err != nil { rest.SendErrorJSON(w, r, http.StatusUnauthorized, err, "can't get user info") return } - locator := store.Locator{SiteID: r.URL.Query().Get("site"), URL: r.URL.Query().Get("url")} status := "not subscribed" - if st, err := s.Notifier.Status(locator, user); err == nil && st { + if st, err := s.Notifier.Status(user); err == nil && st { status = "subscribed" } - render.JSON(w, r, JSON{"locator": locator, "user": user.ID, "status": status}) + render.JSON(w, r, JSON{"user": user.ID, "status": status}) } // serves static files from /web func (s *Rest) addFileServer(r chi.Router, path string, root http.FileSystem) { - log.Printf("[INFO] run file server for %s", root) + log.Printf("[INFO] run file server for %s, path %s", root, path) + origPath := path fs := http.StripPrefix(path, http.FileServer(root)) if path != "/" && path[len(path)-1] != '/' { r.Get(path, http.RedirectHandler(path+"/", 301).ServeHTTP) @@ -513,7 +512,7 @@ func (s *Rest) addFileServer(r chi.Router, path string, root http.FileSystem) { r.Get(path, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // don't show dirs, just serve files - if strings.HasSuffix(r.URL.Path, "/") && len(r.URL.Path) > 1 && r.URL.Path != "/web/" { + if strings.HasSuffix(r.URL.Path, "/") && len(r.URL.Path) > 1 && r.URL.Path != (origPath+"/") { http.NotFound(w, r) return } @@ -536,7 +535,7 @@ func encodeJSONWithHTML(v interface{}) ([]byte, error) { enc := json.NewEncoder(buf) enc.SetEscapeHTML(false) if err := enc.Encode(v); err != nil { - return nil, errors.Wrap(err, "can't encode to json") + return nil, errors.Wrap(err, "json encoding failed") } return buf.Bytes(), nil } @@ -548,6 +547,6 @@ func renderJSONFromBytes(w http.ResponseWriter, r *http.Request, data []byte) { w.WriteHeader(status) } if _, err := w.Write(data); err != nil { - log.Printf("[WARN] can't send response to %s, %s", r.RemoteAddr, err) + log.Printf("[WARN] failed to send response to %s, %s", r.RemoteAddr, err) } } diff --git a/remark.rest b/remark.rest index 6065a45d..6edfa5c4 100644 --- a/remark.rest +++ b/remark.rest @@ -59,7 +59,7 @@ GET {{host}}/api/v1/id/a2ddb8d2f65008ee1a1e3af8df0f26beb042309c?site=remark&url= ### get comment by user id GET {{host}}/api/v1/comments?site=remark&user=disqus_umputun -### get counts +### get count GET {{host}}/api/v1/count?site=remark&url=https://radio-t.com/p/2017/12/16/podcast-576/ ### get counts for many