Add account {,un}subscribe
authorr <r@freesoftwareextremist.com>
Fri, 17 Apr 2020 17:19:11 +0000 (17:19 +0000)
committerr <r@freesoftwareextremist.com>
Fri, 17 Apr 2020 17:31:32 +0000 (17:31 +0000)
mastodon/accounts.go
service/auth.go
service/logging.go
service/service.go
service/transport.go
templates/user.tmpl

index c02f0bd7a626cfc9f8c875298f623c7527dc5c89..995741cfb2b0b6f69235840cfb02e8029ed518f4 100644 (file)
@@ -191,6 +191,7 @@ type Relationship struct {
        Blocking            bool   `json:"blocking"`
        Muting              bool   `json:"muting"`
        MutingNotifications bool   `json:"muting_notifications"`
+       Subscribing         bool   `json:"subscribing"`
        Requested           bool   `json:"requested"`
        DomainBlocking      bool   `json:"domain_blocking"`
        ShowingReblogs      bool   `json:"showing_reblogs"`
@@ -328,3 +329,23 @@ func (c *Client) GetMutes(ctx context.Context, pg *Pagination) ([]*Account, erro
        }
        return accounts, nil
 }
+
+// Subscribe to receive notifications for all statuses posted by a user
+func (c *Client) Subscribe(ctx context.Context, id string) (*Relationship, error) {
+       var relationship *Relationship
+       err := c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/pleroma/accounts/%s/subscribe", url.PathEscape(id)), nil, &relationship, nil)
+       if err != nil {
+               return nil, err
+       }
+       return relationship, nil
+}
+
+// UnSubscribe to stop receiving notifications from user statuses
+func (c *Client) UnSubscribe(ctx context.Context, id string) (*Relationship, error) {
+       var relationship *Relationship
+       err := c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/pleroma/accounts/%s/unsubscribe", url.PathEscape(id)), nil, &relationship, nil)
+       if err != nil {
+               return nil, err
+       }
+       return relationship, nil
+}
index 7fd238bae24229843f2c2c8db429f3290418c4da..dd114b4e965ffa7c1e1232393b82d6ef364178a6 100644 (file)
@@ -364,6 +364,30 @@ func (s *as) UnBlock(ctx context.Context, c *model.Client, id string) (err error
        return s.Service.UnBlock(ctx, c, id)
 }
 
+func (s *as) Subscribe(ctx context.Context, c *model.Client, id string) (err error) {
+       err = s.authenticateClient(ctx, c)
+       if err != nil {
+               return
+       }
+       err = checkCSRF(ctx, c)
+       if err != nil {
+               return
+       }
+       return s.Service.Subscribe(ctx, c, id)
+}
+
+func (s *as) UnSubscribe(ctx context.Context, c *model.Client, id string) (err error) {
+       err = s.authenticateClient(ctx, c)
+       if err != nil {
+               return
+       }
+       err = checkCSRF(ctx, c)
+       if err != nil {
+               return
+       }
+       return s.Service.UnSubscribe(ctx, c, id)
+}
+
 func (s *as) SaveSettings(ctx context.Context, c *model.Client, settings *model.Settings) (err error) {
        err = s.authenticateClient(ctx, c)
        if err != nil {
index 295595931aef4f6e17f81a12184db8e103e38085..c16cdb337885c6ffb2f2d9288941feacef9ad70a 100644 (file)
@@ -269,6 +269,22 @@ func (s *ls) UnBlock(ctx context.Context, c *model.Client, id string) (err error
        return s.Service.UnBlock(ctx, c, id)
 }
 
+func (s *ls) Subscribe(ctx context.Context, c *model.Client, id string) (err error) {
+       defer func(begin time.Time) {
+               s.logger.Printf("method=%v, id=%v, took=%v, err=%v\n",
+                       "Subscribe", id, time.Since(begin), err)
+       }(time.Now())
+       return s.Service.Subscribe(ctx, c, id)
+}
+
+func (s *ls) UnSubscribe(ctx context.Context, c *model.Client, id string) (err error) {
+       defer func(begin time.Time) {
+               s.logger.Printf("method=%v, id=%v, took=%v, err=%v\n",
+                       "UnSubscribe", id, time.Since(begin), err)
+       }(time.Now())
+       return s.Service.UnSubscribe(ctx, c, id)
+}
+
 func (s *ls) SaveSettings(ctx context.Context, c *model.Client, settings *model.Settings) (err error) {
        defer func(begin time.Time) {
                s.logger.Printf("method=%v, took=%v, err=%v\n",
index b039849d1d26f7f76ad28ffd9ea5afed2f1f2dc1..3a48e77d34a5cfdd8bc2b0ef4289f6ade449bd92 100644 (file)
@@ -52,6 +52,8 @@ type Service interface {
        UnMute(ctx context.Context, c *model.Client, id string) (err error)
        Block(ctx context.Context, c *model.Client, id string) (err error)
        UnBlock(ctx context.Context, c *model.Client, id string) (err error)
+       Subscribe(ctx context.Context, c *model.Client, id string) (err error)
+       UnSubscribe(ctx context.Context, c *model.Client, id string) (err error)
        SaveSettings(ctx context.Context, c *model.Client, settings *model.Settings) (err error)
        MuteConversation(ctx context.Context, c *model.Client, id string) (err error)
        UnMuteConversation(ctx context.Context, c *model.Client, id string) (err error)
@@ -839,6 +841,16 @@ func (svc *service) UnBlock(ctx context.Context, c *model.Client, id string) (er
        return
 }
 
+func (svc *service) Subscribe(ctx context.Context, c *model.Client, id string) (err error) {
+       _, err = c.Subscribe(ctx, id)
+       return
+}
+
+func (svc *service) UnSubscribe(ctx context.Context, c *model.Client, id string) (err error) {
+       _, err = c.UnSubscribe(ctx, id)
+       return
+}
+
 func (svc *service) SaveSettings(ctx context.Context, c *model.Client,
        settings *model.Settings) (err error) {
 
index 6540333135211be253772f736d9bc3f863b5cc84..108cc18b5367ee8985bac3605bd18077aebfedbf 100644 (file)
@@ -549,6 +549,38 @@ func NewHandler(s Service, staticDir string) http.Handler {
                w.WriteHeader(http.StatusFound)
        }
 
+       subscribe := func(w http.ResponseWriter, req *http.Request) {
+               c := newClient(w)
+               ctx := newCtxWithSesionCSRF(req, req.FormValue("csrf_token"))
+               id, _ := mux.Vars(req)["id"]
+
+               err := s.Subscribe(ctx, c, id)
+               if err != nil {
+                       w.WriteHeader(http.StatusInternalServerError)
+                       s.ServeErrorPage(ctx, c, err)
+                       return
+               }
+
+               w.Header().Add("Location", req.Header.Get("Referer"))
+               w.WriteHeader(http.StatusFound)
+       }
+
+       unSubscribe := func(w http.ResponseWriter, req *http.Request) {
+               c := newClient(w)
+               ctx := newCtxWithSesionCSRF(req, req.FormValue("csrf_token"))
+               id, _ := mux.Vars(req)["id"]
+
+               err := s.UnSubscribe(ctx, c, id)
+               if err != nil {
+                       w.WriteHeader(http.StatusInternalServerError)
+                       s.ServeErrorPage(ctx, c, err)
+                       return
+               }
+
+               w.Header().Add("Location", req.Header.Get("Referer"))
+               w.WriteHeader(http.StatusFound)
+       }
+
        settings := func(w http.ResponseWriter, req *http.Request) {
                c := newClient(w)
                ctx := newCtxWithSesionCSRF(req, req.FormValue("csrf_token"))
@@ -762,6 +794,8 @@ func NewHandler(s Service, staticDir string) http.Handler {
        r.HandleFunc("/unmute/{id}", unMute).Methods(http.MethodPost)
        r.HandleFunc("/block/{id}", block).Methods(http.MethodPost)
        r.HandleFunc("/unblock/{id}", unBlock).Methods(http.MethodPost)
+       r.HandleFunc("/subscribe/{id}", subscribe).Methods(http.MethodPost)
+       r.HandleFunc("/unsubscribe/{id}", unSubscribe).Methods(http.MethodPost)
        r.HandleFunc("/settings", settings).Methods(http.MethodPost)
        r.HandleFunc("/muteconv/{id}", muteConversation).Methods(http.MethodPost)
        r.HandleFunc("/unmuteconv/{id}", unMuteConversation).Methods(http.MethodPost)
index 6ea79f7a5131b61dbbda59d79898b6d1a8c5b294..848ca0a9d4a93e3c64b5710dd81d3d41bea5d2e0 100644 (file)
                                <input type="hidden" name="csrf_token" value="{{$.Ctx.CSRFToken}}">
                                <input type="submit" value="unfollow" class="btn-link">
                        </form>
-                       {{else}} 
+                       {{else}}
                        <form class="d-inline" action="/follow/{{.User.ID}}" method="post">
                                <input type="hidden" name="csrf_token" value="{{$.Ctx.CSRFToken}}">
                                <input type="submit" value="{{if .User.Pleroma.Relationship.Requested}}resend request{{else}}follow{{end}}" class="btn-link">
                        </form>
                        {{end}}
-                       {{if .User.Pleroma.Relationship.Requested}} 
+                       {{if .User.Pleroma.Relationship.Requested}}
                        -
                        <form class="d-inline" action="/unfollow/{{.User.ID}}" method="post">
                                <input type="hidden" name="csrf_token" value="{{$.Ctx.CSRFToken}}">
                                <input type="submit" value="cancel request" class="btn-link">
                        </form>
-                       {{end}} 
+                       {{end}}
+                       -
+                       {{if .User.Pleroma.Relationship.Subscribing}}
+                       <form class="d-inline" action="/unsubscribe/{{.User.ID}}" method="post">
+                               <input type="hidden" name="csrf_token" value="{{$.Ctx.CSRFToken}}">
+                               <input type="submit" value="unsubscribe" class="btn-link">
+                       </form>
+                       {{else}}
+                       <form class="d-inline" action="/subscribe/{{.User.ID}}" method="post">
+                               <input type="hidden" name="csrf_token" value="{{$.Ctx.CSRFToken}}">
+                               <input type="submit" value="subscribe" class="btn-link">
+                       </form>
+                       {{end}}
                </div>
                <div>
-                       {{if .User.Pleroma.Relationship.Blocking}} 
+                       {{if .User.Pleroma.Relationship.Blocking}}
                        <form class="d-inline" action="/unblock/{{.User.ID}}" method="post">
                                <input type="hidden" name="csrf_token" value="{{$.Ctx.CSRFToken}}">
                                <input type="submit" value="unblock" class="btn-link">
                        </form>
-                       {{else}} 
+                       {{else}}
                        <form class="d-inline" action="/block/{{.User.ID}}" method="post">
                                <input type="hidden" name="csrf_token" value="{{$.Ctx.CSRFToken}}">
                                <input type="submit" value="block" class="btn-link">
                        </form>
-                       {{end}} 
+                       {{end}}
                        -
-                       {{if .User.Pleroma.Relationship.Muting}} 
+                       {{if .User.Pleroma.Relationship.Muting}}
                        <form class="d-inline" action="/unmute/{{.User.ID}}" method="post">
                                <input type="hidden" name="csrf_token" value="{{$.Ctx.CSRFToken}}">
                                <input type="submit" value="unmute" class="btn-link">
                        </form>
-                       {{else}} 
+                       {{else}}
                        <form class="d-inline" action="/mute/{{.User.ID}}" method="post">
                                <input type="hidden" name="csrf_token" value="{{$.Ctx.CSRFToken}}">
                                <input type="submit" value="mute" class="btn-link">