Ability to ignore friend requests
This commit is contained in:
parent
61c47c032d
commit
a97ed4562e
|
@ -4,6 +4,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.nonshy.com/nonshy/website/pkg/config"
|
"code.nonshy.com/nonshy/website/pkg/config"
|
||||||
|
"code.nonshy.com/nonshy/website/pkg/log"
|
||||||
"code.nonshy.com/nonshy/website/pkg/models"
|
"code.nonshy.com/nonshy/website/pkg/models"
|
||||||
"code.nonshy.com/nonshy/website/pkg/session"
|
"code.nonshy.com/nonshy/website/pkg/session"
|
||||||
"code.nonshy.com/nonshy/website/pkg/templates"
|
"code.nonshy.com/nonshy/website/pkg/templates"
|
||||||
|
@ -17,6 +18,7 @@ func Friends() http.HandlerFunc {
|
||||||
view = r.FormValue("view")
|
view = r.FormValue("view")
|
||||||
isRequests = view == "requests"
|
isRequests = view == "requests"
|
||||||
isPending = view == "pending"
|
isPending = view == "pending"
|
||||||
|
isIgnored = view == "ignored"
|
||||||
)
|
)
|
||||||
|
|
||||||
currentUser, err := session.CurrentUser(r)
|
currentUser, err := session.CurrentUser(r)
|
||||||
|
@ -32,7 +34,7 @@ func Friends() http.HandlerFunc {
|
||||||
Sort: "updated_at desc",
|
Sort: "updated_at desc",
|
||||||
}
|
}
|
||||||
pager.ParsePage(r)
|
pager.ParsePage(r)
|
||||||
friends, err := models.PaginateFriends(currentUser, isRequests, isPending, pager)
|
friends, err := models.PaginateFriends(currentUser, isRequests, isPending, isIgnored, pager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
session.FlashError(w, r, "Couldn't paginate friends: %s", err)
|
session.FlashError(w, r, "Couldn't paginate friends: %s", err)
|
||||||
templates.Redirect(w, "/")
|
templates.Redirect(w, "/")
|
||||||
|
@ -42,10 +44,18 @@ func Friends() http.HandlerFunc {
|
||||||
// Inject relationship booleans.
|
// Inject relationship booleans.
|
||||||
models.SetUserRelationships(currentUser, friends)
|
models.SetUserRelationships(currentUser, friends)
|
||||||
|
|
||||||
|
// Ignored friend request count.
|
||||||
|
ignoredFriendCount, err := models.CountIgnoredFriendRequests(currentUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Ignored Friend Request Count (%s): %s", currentUser.Username, err)
|
||||||
|
}
|
||||||
|
|
||||||
var vars = map[string]interface{}{
|
var vars = map[string]interface{}{
|
||||||
"IsRequests": isRequests,
|
"IsRequests": isRequests,
|
||||||
"IsPending": isPending,
|
"IsPending": isPending,
|
||||||
|
"IsIgnored": isIgnored,
|
||||||
"Friends": friends,
|
"Friends": friends,
|
||||||
|
"IgnoredFriendCount": ignoredFriendCount,
|
||||||
"Pager": pager,
|
"Pager": pager,
|
||||||
}
|
}
|
||||||
if err := tmpl.Execute(w, r, vars); err != nil {
|
if err := tmpl.Execute(w, r, vars); err != nil {
|
||||||
|
|
|
@ -71,6 +71,15 @@ func AddFriend() http.HandlerFunc {
|
||||||
templates.Redirect(w, "/friends?view=requests")
|
templates.Redirect(w, "/friends?view=requests")
|
||||||
}
|
}
|
||||||
templates.Redirect(w, "/friends")
|
templates.Redirect(w, "/friends")
|
||||||
|
return
|
||||||
|
} else if verdict == "ignore" {
|
||||||
|
if err := models.IgnoreFriendRequest(currentUser, user); err != nil {
|
||||||
|
session.FlashError(w, r, "Error marking the friend request as ignored: %s", err)
|
||||||
|
} else {
|
||||||
|
session.Flash(w, r, "You have ignored the friend request from %s.", username)
|
||||||
|
}
|
||||||
|
templates.Redirect(w, "/friends")
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
// Post the friend request.
|
// Post the friend request.
|
||||||
if err := models.AddFriend(currentUser.ID, user.ID); err != nil {
|
if err := models.AddFriend(currentUser.ID, user.ID); err != nil {
|
||||||
|
|
|
@ -44,14 +44,6 @@ func SiteGallery() http.HandlerFunc {
|
||||||
sort = sortWhitelist[0]
|
sort = sortWhitelist[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defaults.
|
|
||||||
if viewStyle != "full" {
|
|
||||||
viewStyle = "cards"
|
|
||||||
}
|
|
||||||
if who != "friends" && who != "everybody" {
|
|
||||||
who = "friends"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the current user.
|
// Load the current user.
|
||||||
currentUser, err := session.CurrentUser(r)
|
currentUser, err := session.CurrentUser(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -59,7 +51,23 @@ func SiteGallery() http.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is the current viewer shy?
|
// Is the current viewer shy?
|
||||||
var isShy = currentUser.IsShy()
|
var (
|
||||||
|
isShy = currentUser.IsShy()
|
||||||
|
myFriendCount = models.CountFriends(currentUser.ID)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Defaults.
|
||||||
|
if viewStyle != "full" {
|
||||||
|
viewStyle = "cards"
|
||||||
|
}
|
||||||
|
if who != "friends" && who != "everybody" {
|
||||||
|
// Default Who setting should be Friends-only, unless you have no friends.
|
||||||
|
if myFriendCount > 0 {
|
||||||
|
who = "friends"
|
||||||
|
} else {
|
||||||
|
who = "everybody"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Admin scope warning.
|
// Admin scope warning.
|
||||||
if adminView && !currentUser.HasAdminScope(config.ScopePhotoModerator) {
|
if adminView && !currentUser.HasAdminScope(config.ScopePhotoModerator) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ type Friend struct {
|
||||||
SourceUserID uint64 `gorm:"index"`
|
SourceUserID uint64 `gorm:"index"`
|
||||||
TargetUserID uint64 `gorm:"index"`
|
TargetUserID uint64 `gorm:"index"`
|
||||||
Approved bool `gorm:"index"`
|
Approved bool `gorm:"index"`
|
||||||
|
Ignored bool
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
}
|
}
|
||||||
|
@ -39,6 +40,7 @@ func AddFriend(sourceUserID, targetUserID uint64) error {
|
||||||
if reverse == nil && forward != nil {
|
if reverse == nil && forward != nil {
|
||||||
// Approve the reverse.
|
// Approve the reverse.
|
||||||
rev.Approved = true
|
rev.Approved = true
|
||||||
|
rev.Ignored = false
|
||||||
rev.Save()
|
rev.Save()
|
||||||
|
|
||||||
// Add the matching forward.
|
// Add the matching forward.
|
||||||
|
@ -46,6 +48,7 @@ func AddFriend(sourceUserID, targetUserID uint64) error {
|
||||||
SourceUserID: sourceUserID,
|
SourceUserID: sourceUserID,
|
||||||
TargetUserID: targetUserID,
|
TargetUserID: targetUserID,
|
||||||
Approved: true,
|
Approved: true,
|
||||||
|
Ignored: false,
|
||||||
}
|
}
|
||||||
return DB.Create(f).Error
|
return DB.Create(f).Error
|
||||||
}
|
}
|
||||||
|
@ -240,13 +243,25 @@ func FriendIDsInCircleAreExplicit(userId uint64) []uint64 {
|
||||||
func CountFriendRequests(userID uint64) (int64, error) {
|
func CountFriendRequests(userID uint64) (int64, error) {
|
||||||
var count int64
|
var count int64
|
||||||
result := DB.Where(
|
result := DB.Where(
|
||||||
"target_user_id = ? AND approved = ?",
|
"target_user_id = ? AND approved = ? AND ignored IS NOT true",
|
||||||
userID,
|
userID,
|
||||||
false,
|
false,
|
||||||
).Model(&Friend{}).Count(&count)
|
).Model(&Friend{}).Count(&count)
|
||||||
return count, result.Error
|
return count, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountIgnoredFriendRequests gets a count of ignored pending friend requests for the user.
|
||||||
|
func CountIgnoredFriendRequests(userID uint64) (int64, error) {
|
||||||
|
var count int64
|
||||||
|
result := DB.Where(
|
||||||
|
"target_user_id = ? AND approved = ? AND ignored = ?",
|
||||||
|
userID,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
).Model(&Friend{}).Count(&count)
|
||||||
|
return count, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
// CountFriends gets a count of friends for the user.
|
// CountFriends gets a count of friends for the user.
|
||||||
func CountFriends(userID uint64) int64 {
|
func CountFriends(userID uint64) int64 {
|
||||||
var count int64
|
var count int64
|
||||||
|
@ -269,7 +284,7 @@ The `requests` and `sent` bools are mutually exclusive (use only one, or neither
|
||||||
asks for unanswered friend requests to you, and `sent` returns the friend requests that you
|
asks for unanswered friend requests to you, and `sent` returns the friend requests that you
|
||||||
have sent and have not been answered.
|
have sent and have not been answered.
|
||||||
*/
|
*/
|
||||||
func PaginateFriends(user *User, requests bool, sent bool, pager *Pagination) ([]*User, error) {
|
func PaginateFriends(user *User, requests bool, sent bool, ignored bool, pager *Pagination) ([]*User, error) {
|
||||||
// We paginate over the Friend table.
|
// We paginate over the Friend table.
|
||||||
var (
|
var (
|
||||||
fs = []*Friend{}
|
fs = []*Friend{}
|
||||||
|
@ -277,20 +292,25 @@ func PaginateFriends(user *User, requests bool, sent bool, pager *Pagination) ([
|
||||||
query *gorm.DB
|
query *gorm.DB
|
||||||
)
|
)
|
||||||
|
|
||||||
if requests && sent {
|
if requests && sent && ignored {
|
||||||
return nil, errors.New("requests and sent are mutually exclusive options, use one or neither")
|
return nil, errors.New("requests and sent are mutually exclusive options, use one or neither")
|
||||||
}
|
}
|
||||||
|
|
||||||
if requests {
|
if requests {
|
||||||
query = DB.Where(
|
query = DB.Where(
|
||||||
"target_user_id = ? AND approved = ?",
|
"target_user_id = ? AND approved = ? AND ignored IS NOT true",
|
||||||
user.ID, false,
|
user.ID, false,
|
||||||
)
|
)
|
||||||
} else if sent {
|
} else if sent {
|
||||||
query = DB.Where(
|
query = DB.Where(
|
||||||
"source_user_id = ? AND approved = ?",
|
"source_user_id = ? AND approved = ? AND ignored IS NOT true",
|
||||||
user.ID, false,
|
user.ID, false,
|
||||||
)
|
)
|
||||||
|
} else if ignored {
|
||||||
|
query = DB.Where(
|
||||||
|
"target_user_id = ? AND approved = ? AND ignored = ?",
|
||||||
|
user.ID, false, true,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
query = DB.Where(
|
query = DB.Where(
|
||||||
"source_user_id = ? AND approved = ?",
|
"source_user_id = ? AND approved = ?",
|
||||||
|
@ -307,7 +327,7 @@ func PaginateFriends(user *User, requests bool, sent bool, pager *Pagination) ([
|
||||||
|
|
||||||
// Now of these friends get their User objects.
|
// Now of these friends get their User objects.
|
||||||
for _, friend := range fs {
|
for _, friend := range fs {
|
||||||
if requests {
|
if requests || ignored {
|
||||||
userIDs = append(userIDs, friend.SourceUserID)
|
userIDs = append(userIDs, friend.SourceUserID)
|
||||||
} else {
|
} else {
|
||||||
userIDs = append(userIDs, friend.TargetUserID)
|
userIDs = append(userIDs, friend.TargetUserID)
|
||||||
|
@ -384,6 +404,28 @@ func GetFriendRequests(userID uint64) ([]*Friend, error) {
|
||||||
return fs, result.Error
|
return fs, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IgnoreFriendRequest ignores a pending friend request that was sent to targetUserID.
|
||||||
|
func IgnoreFriendRequest(currentUser *User, fromUser *User) error {
|
||||||
|
// Is there a reverse friend request pending? (The one we ideally hope to mark Ignored)
|
||||||
|
rev := &Friend{}
|
||||||
|
reverse := DB.Where(
|
||||||
|
"source_user_id = ? AND target_user_id = ?",
|
||||||
|
fromUser.ID, currentUser.ID,
|
||||||
|
).First(&rev).Error
|
||||||
|
|
||||||
|
// If the reverse exists (requested us) mark it as Ignored.
|
||||||
|
if reverse == nil {
|
||||||
|
// Ignore the reverse friend request (happy path).
|
||||||
|
log.Error("%s ignoring friend request from %s", currentUser.Username, fromUser.Username)
|
||||||
|
rev.Approved = false
|
||||||
|
rev.Ignored = true
|
||||||
|
return rev.Save()
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Error("rev: %+v", rev)
|
||||||
|
return errors.New("unexpected error while ignoring friend request")
|
||||||
|
}
|
||||||
|
|
||||||
// RemoveFriend severs a friend connection both directions, used when
|
// RemoveFriend severs a friend connection both directions, used when
|
||||||
// rejecting a request or removing a friend.
|
// rejecting a request or removing a friend.
|
||||||
func RemoveFriend(sourceUserID, targetUserID uint64) error {
|
func RemoveFriend(sourceUserID, targetUserID uint64) error {
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
<div class="tabs is-toggle">
|
<div class="tabs is-toggle">
|
||||||
<ul>
|
<ul>
|
||||||
<li{{if and (not .IsRequests) (not .IsPending)}} class="is-active"{{end}}>
|
<li{{if and (not .IsRequests) (not .IsPending) (not .IsIgnored)}} class="is-active"{{end}}>
|
||||||
<a href="/friends">My Friends</a>
|
<a href="/friends">My Friends</a>
|
||||||
</li>
|
</li>
|
||||||
<li{{if .IsRequests}} class="is-active"{{end}}>
|
<li{{if .IsRequests}} class="is-active"{{end}}>
|
||||||
|
@ -32,6 +32,12 @@
|
||||||
Sent
|
Sent
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li{{if .IsIgnored}} class="is-active"{{end}}>
|
||||||
|
<a href="/friends?view=ignored">
|
||||||
|
Ignored
|
||||||
|
{{if .IgnoredFriendCount}}<span class="tag ml-2">{{.IgnoredFriendCount}}</span>{{end}}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -52,6 +58,7 @@
|
||||||
{{Pluralize64 .Pager.Total "has" "have"}} not been approved yet.
|
{{Pluralize64 .Pager.Total "has" "have"}} not been approved yet.
|
||||||
{{else}}
|
{{else}}
|
||||||
You have {{.Pager.Total}} friend{{if .IsRequests}} request{{end}}{{Pluralize64 .Pager.Total}}
|
You have {{.Pager.Total}} friend{{if .IsRequests}} request{{end}}{{Pluralize64 .Pager.Total}}
|
||||||
|
{{if .IsIgnored}} on ignore -- they don't know you ignored their request and they can not send another one.{{end}}
|
||||||
(page {{.Pager.Page}} of {{.Pager.Pages}}).
|
(page {{.Pager.Page}} of {{.Pager.Pages}}).
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -108,7 +115,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{if $Root.IsRequests}}
|
{{if or $Root.IsRequests $Root.IsIgnored}}
|
||||||
<footer class="card-footer">
|
<footer class="card-footer">
|
||||||
<button type="submit" name="verdict" value="approve" class="card-footer-item button is-success">
|
<button type="submit" name="verdict" value="approve" class="card-footer-item button is-success">
|
||||||
<span class="icon"><i class="fa fa-check"></i></span>
|
<span class="icon"><i class="fa fa-check"></i></span>
|
||||||
|
@ -118,6 +125,12 @@
|
||||||
<span class="icon"><i class="fa fa-xmark"></i></span>
|
<span class="icon"><i class="fa fa-xmark"></i></span>
|
||||||
<span>Reject</span>
|
<span>Reject</span>
|
||||||
</button>
|
</button>
|
||||||
|
{{if not $Root.IsIgnored}}
|
||||||
|
<button type="submit" name="verdict" value="ignore" class="card-footer-item button">
|
||||||
|
<span class="icon"><i class="fa fa-moon"></i></span>
|
||||||
|
<span>Ignore</span>
|
||||||
|
</button>
|
||||||
|
{{end}}
|
||||||
</footer>
|
</footer>
|
||||||
{{else}}
|
{{else}}
|
||||||
<footer class="card-footer">
|
<footer class="card-footer">
|
||||||
|
|
Loading…
Reference in New Issue
Block a user