From 9bbd544a206bdd1e3008aa7ffb5fc354c2daf351 Mon Sep 17 00:00:00 2001 From: akuma06 Date: Wed, 10 May 2017 03:15:29 +0200 Subject: [PATCH] Added Follow&Unfollow --- model/user.go | 4 +-- router/router.go | 2 ++ router/templateFunctions.go | 5 ++-- router/templateVariables.go | 1 + router/userHandler.go | 37 +++++++++++++++++++++++++-- service/user/permission/permission.go | 10 ++++++++ service/user/user.go | 21 ++++++++++++++- templates/user/profile.html | 9 ++++++- templates/user/profile_edit.html | 6 ++++- translations/en-us.all.json | 12 +++++++++ 10 files changed, 98 insertions(+), 9 deletions(-) diff --git a/model/user.go b/model/user.go index 17452159..04601459 100644 --- a/model/user.go +++ b/model/user.go @@ -19,8 +19,8 @@ type User struct { // TODO: move this to PublicUser LikingCount int `json:"likingCount" gorm:"-"` LikedCount int `json:"likedCount" gorm:"-"` - Likings []User `gorm:"foreignkey:userId;associationforeignkey:follower_id;many2many:user_follows"` - Liked []User `gorm:"foreignkey:follower_id;associationforeignkey:userId;many2many:user_follows"` + Likings []User // Don't work `gorm:"foreignkey:user_id;associationforeignkey:follower_id;many2many:user_follows"` + Liked []User // Don't work `gorm:"foreignkey:follower_id;associationforeignkey:user_id;many2many:user_follows"` Md5 string `json:"md5"` // Used for gravatar Torrents []Torrents `gorm:"ForeignKey:UploaderId"` diff --git a/router/router.go b/router/router.go index ff02dccc..32a97dcd 100644 --- a/router/router.go +++ b/router/router.go @@ -36,6 +36,7 @@ func init() { gzipUserLoginPostHandler := handlers.CompressHandler(http.HandlerFunc(UserLoginPostHandler)) gzipUserLogoutHandler := handlers.CompressHandler(http.HandlerFunc(UserLogoutHandler)) gzipUserProfileHandler := handlers.CompressHandler(http.HandlerFunc(UserProfileHandler)) + gzipUserFollowHandler := handlers.CompressHandler(http.HandlerFunc(UserFollowHandler)) gzipUserProfileFormHandler := handlers.CompressHandler(http.HandlerFunc(UserProfileFormHandler)) Router = mux.NewRouter() @@ -65,6 +66,7 @@ func init() { Router.Handle("/user/login", gzipUserLoginPostHandler).Name("user_login").Methods("POST") Router.Handle("/user/logout", gzipUserLogoutHandler).Name("user_logout") Router.Handle("/user/{id}/{username}", gzipUserProfileHandler).Name("user_profile").Methods("GET") + Router.Handle("/user/{id}/{username}/follow", gzipUserFollowHandler).Name("user_follow").Methods("GET") Router.Handle("/user/{id}/{username}", gzipUserProfileFormHandler).Name("user_profile").Methods("POST") Router.PathPrefix("/captcha").Methods("GET").HandlerFunc(captcha.ServeFiles) diff --git a/router/templateFunctions.go b/router/templateFunctions.go index 14193ca7..0fc3f959 100644 --- a/router/templateFunctions.go +++ b/router/templateFunctions.go @@ -35,10 +35,10 @@ var FuncMap = template.FuncMap{ ret = ret + "
  • «
  • " } startValue := 1 - if nav.CurrentPage > pagesSelectable { + if nav.CurrentPage > pagesSelectable/2 { startValue = (int(math.Min((float64(nav.CurrentPage)+math.Floor(float64(pagesSelectable)/2)), maxPages)) - pagesSelectable + 1) } - endValue := (startValue + pagesSelectable - 1) + endValue := (startValue + pagesSelectable -1) if endValue > int(maxPages) { endValue = int(maxPages) } @@ -67,4 +67,5 @@ var FuncMap = template.FuncMap{ "CurrentUserIdentical": userPermission.CurrentUserIdentical, "HasAdmin": userPermission.HasAdmin, "GetRole": userPermission.GetRole, + "IsFollower": userPermission.IsFollower, } diff --git a/router/templateVariables.go b/router/templateVariables.go index 4f8ca4d7..8d8761e5 100644 --- a/router/templateVariables.go +++ b/router/templateVariables.go @@ -87,6 +87,7 @@ type UserLoginFormVariables struct { type UserProfileVariables struct { UserProfile *model.User + FormInfos map[string][]string Search SearchForm Navigation Navigation User *model.User diff --git a/router/userHandler.go b/router/userHandler.go index 1edc76d2..7fac397b 100644 --- a/router/userHandler.go +++ b/router/userHandler.go @@ -1,7 +1,10 @@ package router import ( + "fmt" "net/http" + "strconv" + "github.com/ewhal/nyaa/model" "github.com/ewhal/nyaa/service/captcha" @@ -56,6 +59,10 @@ func UserProfileHandler(w http.ResponseWriter, r *http.Request) { if (errorUser == nil) { currentUser := GetUser(r) view := r.URL.Query()["edit"] + follow := r.URL.Query()["followed"] + unfollow := r.URL.Query()["unfollowed"] + infosForm := form.NewInfos() + deleteVar := r.URL.Query()["delete"] if ((view != nil)&&(userPermission.CurrentOrAdmin(currentUser, userProfile.Id))) { b := form.UserForm{} @@ -80,8 +87,14 @@ func UserProfileHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, errorTmpl.Error(), http.StatusInternalServerError) } } else { - languages.SetTranslationFromRequest(viewProfileTemplate, r, "en-us") - htv := UserProfileVariables{&userProfile, NewSearchForm(), Navigation{}, currentUser, r.URL, mux.CurrentRoute(r)} + T := languages.SetTranslationFromRequest(viewProfileTemplate, r, "en-us") + if (follow != nil) { + infosForm["infos"] = append(infosForm["infos"], fmt.Sprintf(T("user_followed_msg"), userProfile.Username)) + } + if (unfollow != nil) { + infosForm["infos"] = append(infosForm["infos"], fmt.Sprintf(T("user_unfollowed_msg"), userProfile.Username)) + } + htv := UserProfileVariables{&userProfile, infosForm, NewSearchForm(), Navigation{}, currentUser, r.URL, mux.CurrentRoute(r)} err := viewProfileTemplate.ExecuteTemplate(w, "index.html", htv) if err != nil { @@ -251,3 +264,23 @@ func UserLogoutHandler(w http.ResponseWriter, r *http.Request) { url, _ := Router.Get("home").URL() http.Redirect(w, r, url.String(), http.StatusSeeOther) } + + +func UserFollowHandler(w http.ResponseWriter, r *http.Request) { + var followAction string + vars := mux.Vars(r) + id := vars["id"] + currentUser := GetUser(r) + user, _, errorUser := userService.RetrieveUserForAdmin(id) + if (errorUser == nil) { + if (!userPermission.IsFollower(&user, currentUser)) { + followAction = "followed" + userService.SetFollow(&user, currentUser) + } else { + followAction = "unfollowed" + userService.RemoveFollow(&user, currentUser) + } + } + url, _ := Router.Get("user_profile").URL("id", strconv.Itoa(int(user.Id)), "username", user.Username) + http.Redirect(w, r, url.String()+"?"+followAction, http.StatusSeeOther) +} diff --git a/service/user/permission/permission.go b/service/user/permission/permission.go index 64edb7be..db85c304 100644 --- a/service/user/permission/permission.go +++ b/service/user/permission/permission.go @@ -3,6 +3,7 @@ package userPermission import ( "github.com/ewhal/nyaa/model" "github.com/ewhal/nyaa/util/log" + "github.com/ewhal/nyaa/db" ) // HasAdmin checks that user has an admin permission. @@ -38,3 +39,12 @@ func GetRole(user *model.User) string { } return "Member" } + +func IsFollower(user *model.User, currentUser *model.User) bool { + var likingUserCount int + db.ORM.Model(&model.UserFollows{}).Where("user_id = ? and following = ?", user.Id, currentUser.Id).Count(&likingUserCount) + if likingUserCount != 0 { + return true + } + return false +} \ No newline at end of file diff --git a/service/user/user.go b/service/user/user.go index 641f062c..b2579339 100644 --- a/service/user/user.go +++ b/service/user/user.go @@ -262,6 +262,11 @@ func RetrieveUserForAdmin(id string) (model.User, int, error) { if db.ORM.Preload("Torrents").First(&user, id).RecordNotFound() { return user, http.StatusNotFound, errors.New("User is not found.") } + var liked,likings []model.User + db.ORM.Joins("JOIN user_follows on user_follows.user_id=?", user.Id).Where("users.user_id = user_follows.following").Group("users.user_id").Find(&likings) + db.ORM.Joins("JOIN user_follows on user_follows.following=?", user.Id).Where("users.user_id = user_follows.user_id").Group("users.user_id").Find(&liked) + user.Likings = likings + user.Liked = liked return user, http.StatusOK, nil } @@ -272,7 +277,7 @@ func RetrieveUsersForAdmin() []model.User { db.ORM.Find(&users) for _, user := range users { db.ORM.Model(&user) - db.ORM.Model(&user).Related("Torrents").Find(&model.Torrents{}) + db.ORM.Model(&user).Related("Torrents").Related("Likings").Related("Liked").Find(&model.Torrents{}) userArr = append(userArr, user) } return userArr @@ -287,3 +292,17 @@ func CreateUserAuthentication(w http.ResponseWriter, r *http.Request) (int, erro status, err := SetCookieHandler(w, username, pass) return status, err } + +func SetFollow(user *model.User, follower *model.User) { + if (follower.Id > 0 && user.Id > 0) { + var userFollows = model.UserFollows{UserID: user.Id, FollowerID: follower.Id} + db.ORM.Create(&userFollows) + } +} + +func RemoveFollow(user *model.User, follower *model.User) { + if (follower.Id > 0 && user.Id > 0) { + var userFollows = model.UserFollows{UserID: user.Id, FollowerID: follower.Id} + db.ORM.Delete(&userFollows) + } +} \ No newline at end of file diff --git a/templates/user/profile.html b/templates/user/profile.html index bb46e232..279d8d83 100644 --- a/templates/user/profile.html +++ b/templates/user/profile.html @@ -1,6 +1,9 @@ {{define "title"}}{{ T "profile_page" .UserProfile.Username }}{{end}} {{define "contclass"}}cont-view{{end}} {{define "content"}} +{{ range (index $.FormInfos "infos")}} +
    × {{ . }}
    +{{end}}
    {{with .UserProfile}}
    @@ -24,7 +27,11 @@
    {{if gt $.User.Id 0 }} {{if not (CurrentUserIdentical $.User .Id) }} - + {{if not (IsFollower . $.User)}} + {{ T "follow"}} + {{else}} + {{ T "unfollow"}} + {{end}} {{end}} {{end}} diff --git a/templates/user/profile_edit.html b/templates/user/profile_edit.html index 77b6d50e..667e0eda 100644 --- a/templates/user/profile_edit.html +++ b/templates/user/profile_edit.html @@ -24,7 +24,11 @@
    {{if gt $.User.Id 0 }} {{if not (CurrentUserIdentical $.User .Id) }} - + {{if not (IsFollower . $.User)}} + {{ T "follow"}} + {{else}} + {{ T "unfollow"}} + {{end}} {{end}} {{end}} diff --git a/translations/en-us.all.json b/translations/en-us.all.json index 2a6671cc..179987f3 100644 --- a/translations/en-us.all.json +++ b/translations/en-us.all.json @@ -119,6 +119,18 @@ "id":"follow", "translation": "Follow" }, + { + "id":"unfollow", + "translation": "Unfollow" + }, + { + "id":"user_followed_msg", + "translation": "You have followed %s!" + }, + { + "id":"user_unfollowed_msg", + "translation": "You have unfollowed %s!" + }, { "id":"profile_page", "translation": "%s Profile Page"