From a1f49af1d93bccdd56d4538b149884418bd2ca2c Mon Sep 17 00:00:00 2001 From: r Date: Fri, 20 Dec 2019 18:30:20 +0000 Subject: Add user page and follow/unfollow calls --- service/auth.go | 24 +++++++++++++++++++++ service/logging.go | 24 +++++++++++++++++++++ service/service.go | 52 +++++++++++++++++++++++++++++++++++++++++++++ service/transport.go | 60 +++++++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 152 insertions(+), 8 deletions(-) (limited to 'service') diff --git a/service/auth.go b/service/auth.go index 38c0a43..2b6fdd6 100644 --- a/service/auth.go +++ b/service/auth.go @@ -119,6 +119,14 @@ func (s *authService) ServeNotificationPage(ctx context.Context, client io.Write return s.Service.ServeNotificationPage(ctx, client, c, maxID, minID) } +func (s *authService) ServeUserPage(ctx context.Context, client io.Writer, c *mastodon.Client, id string, maxID string, minID string) (err error) { + c, err = s.getClient(ctx) + if err != nil { + return + } + return s.Service.ServeUserPage(ctx, client, c, id, maxID, minID) +} + func (s *authService) Like(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) { c, err = s.getClient(ctx) if err != nil { @@ -158,3 +166,19 @@ func (s *authService) PostTweet(ctx context.Context, client io.Writer, c *mastod } return s.Service.PostTweet(ctx, client, c, content, replyToID, files) } + +func (s *authService) Follow(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) { + c, err = s.getClient(ctx) + if err != nil { + return + } + return s.Service.Follow(ctx, client, c, id) +} + +func (s *authService) UnFollow(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) { + c, err = s.getClient(ctx) + if err != nil { + return + } + return s.Service.UnFollow(ctx, client, c, id) +} diff --git a/service/logging.go b/service/logging.go index aa1da68..9b398af 100644 --- a/service/logging.go +++ b/service/logging.go @@ -85,6 +85,14 @@ func (s *loggingService) ServeNotificationPage(ctx context.Context, client io.Wr return s.Service.ServeNotificationPage(ctx, client, c, maxID, minID) } +func (s *loggingService) ServeUserPage(ctx context.Context, client io.Writer, c *mastodon.Client, id string, maxID string, minID string) (err error) { + defer func(begin time.Time) { + s.logger.Printf("method=%v, id=%v, max_id=%v, min_id=%v, took=%v, err=%v\n", + "ServeUserPage", id, maxID, minID, time.Since(begin), err) + }(time.Now()) + return s.Service.ServeUserPage(ctx, client, c, id, maxID, minID) +} + func (s *loggingService) Like(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) { defer func(begin time.Time) { s.logger.Printf("method=%v, id=%v, took=%v, err=%v\n", @@ -124,3 +132,19 @@ func (s *loggingService) PostTweet(ctx context.Context, client io.Writer, c *mas }(time.Now()) return s.Service.PostTweet(ctx, client, c, content, replyToID, files) } + +func (s *loggingService) Follow(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) { + defer func(begin time.Time) { + s.logger.Printf("method=%v, id=%v, took=%v, err=%v\n", + "Follow", id, time.Since(begin), err) + }(time.Now()) + return s.Service.Follow(ctx, client, c, id) +} + +func (s *loggingService) UnFollow(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) { + defer func(begin time.Time) { + s.logger.Printf("method=%v, id=%v, took=%v, err=%v\n", + "UnFollow", id, time.Since(begin), err) + }(time.Now()) + return s.Service.UnFollow(ctx, client, c, id) +} diff --git a/service/service.go b/service/service.go index 556afa6..63f74d3 100644 --- a/service/service.go +++ b/service/service.go @@ -32,11 +32,14 @@ type Service interface { ServeTimelinePage(ctx context.Context, client io.Writer, c *mastodon.Client, maxID string, sinceID string, minID string) (err error) ServeThreadPage(ctx context.Context, client io.Writer, c *mastodon.Client, id string, reply bool) (err error) ServeNotificationPage(ctx context.Context, client io.Writer, c *mastodon.Client, maxID string, minID string) (err error) + ServeUserPage(ctx context.Context, client io.Writer, c *mastodon.Client, id string, maxID string, minID string) (err error) Like(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) UnLike(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) Retweet(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) UnRetweet(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) PostTweet(ctx context.Context, client io.Writer, c *mastodon.Client, content string, replyToID string, files []*multipart.FileHeader) (id string, err error) + Follow(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) + UnFollow(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) } type service struct { @@ -369,6 +372,45 @@ func (svc *service) ServeNotificationPage(ctx context.Context, client io.Writer, return } +func (svc *service) ServeUserPage(ctx context.Context, client io.Writer, c *mastodon.Client, id string, maxID string, minID string) (err error) { + user, err := c.GetAccount(ctx, id) + if err != nil { + return + } + + var hasNext bool + var nextLink string + + var pg = mastodon.Pagination{ + MaxID: maxID, + MinID: minID, + Limit: 20, + } + + statuses, err := c.GetAccountStatuses(ctx, id, &pg) + if err != nil { + return + } + + if len(pg.MaxID) > 0 { + hasNext = true + nextLink = "/user/" + id + "?max_id=" + pg.MaxID + } + + navbarData, err := svc.getNavbarTemplateData(ctx, client, c) + if err != nil { + return + } + + data := renderer.NewUserPageTemplateData(user, statuses, hasNext, nextLink, navbarData) + err = svc.renderer.RenderUserPage(ctx, client, data) + if err != nil { + return + } + + return +} + func (svc *service) getNavbarTemplateData(ctx context.Context, client io.Writer, c *mastodon.Client) (data *renderer.NavbarTemplateData, err error) { notifications, err := c.GetNotifications(ctx, nil) if err != nil { @@ -431,6 +473,16 @@ func (svc *service) PostTweet(ctx context.Context, client io.Writer, c *mastodon return s.ID, nil } +func (svc *service) Follow(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) { + _, err = c.AccountFollow(ctx, id) + return +} + +func (svc *service) UnFollow(ctx context.Context, client io.Writer, c *mastodon.Client, id string) (err error) { + _, err = c.AccountUnfollow(ctx, id) + return +} + func addToReplyMap(m map[string][]mastodon.ReplyInfo, key interface{}, val string, number int) { if key == nil { return diff --git a/service/transport.go b/service/transport.go index 1326c58..6759fcc 100644 --- a/service/transport.go +++ b/service/transport.go @@ -15,14 +15,6 @@ var ( cookieAge = "31536000" ) -func getContextWithSession(ctx context.Context, req *http.Request) context.Context { - sessionID, err := req.Cookie("session_id") - if err != nil { - return ctx - } - return context.WithValue(ctx, "session_id", sessionID.Value) -} - func NewHandler(s Service, staticDir string) http.Handler { r := mux.NewRouter() @@ -192,6 +184,50 @@ func NewHandler(s Service, staticDir string) http.Handler { } }).Methods(http.MethodGet) + r.HandleFunc("/user/{id}", func(w http.ResponseWriter, req *http.Request) { + ctx := getContextWithSession(context.Background(), req) + + id, _ := mux.Vars(req)["id"] + maxID := req.URL.Query().Get("max_id") + minID := req.URL.Query().Get("min_id") + + err := s.ServeUserPage(ctx, w, nil, id, maxID, minID) + if err != nil { + s.ServeErrorPage(ctx, w, err) + return + } + }).Methods(http.MethodGet) + + r.HandleFunc("/follow/{id}", func(w http.ResponseWriter, req *http.Request) { + ctx := getContextWithSession(context.Background(), req) + + id, _ := mux.Vars(req)["id"] + + err := s.Follow(ctx, w, nil, id) + if err != nil { + s.ServeErrorPage(ctx, w, err) + return + } + + w.Header().Add("Location", req.Header.Get("Referer")) + w.WriteHeader(http.StatusFound) + }).Methods(http.MethodPost) + + r.HandleFunc("/unfollow/{id}", func(w http.ResponseWriter, req *http.Request) { + ctx := getContextWithSession(context.Background(), req) + + id, _ := mux.Vars(req)["id"] + + err := s.UnFollow(ctx, w, nil, id) + if err != nil { + s.ServeErrorPage(ctx, w, err) + return + } + + w.Header().Add("Location", req.Header.Get("Referer")) + w.WriteHeader(http.StatusFound) + }).Methods(http.MethodPost) + r.HandleFunc("/signout", func(w http.ResponseWriter, req *http.Request) { // TODO remove session from database w.Header().Add("Set-Cookie", fmt.Sprintf("session_id=;max-age=0")) @@ -202,6 +238,14 @@ func NewHandler(s Service, staticDir string) http.Handler { return r } +func getContextWithSession(ctx context.Context, req *http.Request) context.Context { + sessionID, err := req.Cookie("session_id") + if err != nil { + return ctx + } + return context.WithValue(ctx, "session_id", sessionID.Value) +} + func getMultipartFormValue(mf *multipart.Form, key string) (val string) { vals, ok := mf.Value[key] if !ok { -- cgit v1.2.3