Inner circle followups: notifications, min public pictures

face-detect
Noah Petherbridge 2023-05-24 11:27:42 -07:00
parent b9f2bafd7a
commit 6cad3cadc7
6 changed files with 68 additions and 16 deletions

View File

@ -87,6 +87,9 @@ const (
// Quotas for uploaded photos.
PhotoQuotaUncertified = 6
PhotoQuotaCertified = 100
// Min number of public photos for inner circle members to see the prompt to invite.
InnerCircleMinimumPublicPhotos = 5
)
// Forum settings

View File

@ -157,8 +157,14 @@ func notifyFriendsNewPhoto(photo *models.Photo, currentUser *models.User) {
friendIDs = models.PrivateGranteeUserIDs(currentUser.ID)
log.Info("Notify %d private grantees about the new photo by %s", len(friendIDs), currentUser.Username)
} else if photo.Visibility == models.PhotoInnerCircle {
friendIDs = models.FriendIDsInCircle(currentUser.ID)
log.Info("Notify %d circle friends about the new photo by %s", len(friendIDs), currentUser.Username)
// Inner circle members. If the pic is also Explicit, further narrow to explicit friend IDs.
if photo.Explicit {
friendIDs = models.FriendIDsInCircleAreExplicit(currentUser.ID)
log.Info("Notify %d EXPLICIT circle friends about the new photo by %s", len(friendIDs), currentUser.Username)
} else {
friendIDs = models.FriendIDsInCircle(currentUser.ID)
log.Info("Notify %d circle friends about the new photo by %s", len(friendIDs), currentUser.Username)
}
} else {
// Get all our friend IDs. If this photo is Explicit, only select
// the friends who've opted-in for Explicit photo visibility.

View File

@ -139,19 +139,21 @@ func UserPhotos() http.HandlerFunc {
commentMap := models.MapCommentCounts("photos", photoIDs)
var vars = map[string]interface{}{
"IsOwnPhotos": currentUser.ID == user.ID,
"IsShyUser": isShy,
"IsShyFrom": isShyFrom,
"IsMyPrivateUnlockedFor": isGranted, // have WE granted THIS USER to see our private pics?
"AreWeGrantedPrivate": isGrantee, // have THEY granted US private photo access.
"User": user,
"Photos": photos,
"PhotoCount": models.CountPhotos(user.ID),
"Pager": pager,
"LikeMap": likeMap,
"CommentMap": commentMap,
"ViewStyle": viewStyle,
"ExplicitCount": explicitCount,
"IsOwnPhotos": currentUser.ID == user.ID,
"IsShyUser": isShy,
"IsShyFrom": isShyFrom,
"IsMyPrivateUnlockedFor": isGranted, // have WE granted THIS USER to see our private pics?
"AreWeGrantedPrivate": isGrantee, // have THEY granted US private photo access.
"User": user,
"Photos": photos,
"PhotoCount": models.CountPhotos(user.ID),
"PublicPhotoCount": models.CountPublicPhotos(user.ID),
"InnerCircleMinimumPublicPhotos": config.InnerCircleMinimumPublicPhotos,
"Pager": pager,
"LikeMap": likeMap,
"CommentMap": commentMap,
"ViewStyle": viewStyle,
"ExplicitCount": explicitCount,
}
if err := tmpl.Execute(w, r, vars); err != nil {

View File

@ -155,6 +155,31 @@ func FriendIDsInCircle(userId uint64) []uint64 {
return userIDs
}
// FriendIDsInCircleAreExplicit returns the combined friend IDs who are in the inner circle + have opted in to explicit content.
// It is the combination of FriendIDsAreExplicit and FriendIDsInCircle.
func FriendIDsInCircleAreExplicit(userId uint64) []uint64 {
var (
userIDs = []uint64{}
)
err := DB.Table(
"friends",
).Joins(
"JOIN users ON (users.id = friends.target_user_id)",
).Select(
"friends.target_user_id AS friend_id",
).Where(
"friends.source_user_id = ? AND friends.approved = ? AND users.explicit = ? AND (users.inner_circle = ? OR users.is_admin = ?)",
userId, true, true, true, true,
).Scan(&userIDs)
if err.Error != nil {
log.Error("SQL error collecting explicit FriendIDs for %d: %s", userId, err)
}
return userIDs
}
// CountFriendRequests gets a count of pending requests for the user.
func CountFriendRequests(userID uint64) (int64, error) {
var count int64

View File

@ -159,6 +159,22 @@ func CountExplicitPhotos(userID uint64, visibility []PhotoVisibility) (int64, er
return count, result.Error
}
// CountPublicPhotos returns the number of public photos on a user's page (to control whether the "invite to circle" prompt can appear).
func CountPublicPhotos(userID uint64) int64 {
query := DB.Where(
"user_id = ? AND visibility = ?",
userID,
PhotoPublic,
)
var count int64
result := query.Model(&Photo{}).Count(&count)
if result.Error != nil {
log.Error("CountPublicPhotos(%d): %s", userID, result.Error)
}
return count
}
// DistinctPhotoTypes returns types of photos the user has: a set of public, friends, or private.
//
// The result is cached on the User the first time it's queried.

View File

@ -342,7 +342,7 @@
<!-- Inner circle invitation -->
{{if not .IsSiteGallery}}
{{if and (.CurrentUser.IsInnerCircle) (not .User.InnerCircle) (ne .CurrentUser.Username .User.Username)}}
{{if and (.CurrentUser.IsInnerCircle) (not .User.InnerCircle) (ne .CurrentUser.Username .User.Username) (ge .PublicPhotoCount .InnerCircleMinimumPublicPhotos)}}
<div class="block mt-0">
<span class="icon"><img src="/static/img/circle-16.png"></span>
Does <strong>{{.User.Username}}</strong> show a lot of nudity? Consider