Notifications about new photo uploads for your friends

This commit is contained in:
Noah Petherbridge 2023-03-16 20:04:43 -07:00
parent eb913844f7
commit f98b6b2806
5 changed files with 104 additions and 3 deletions

View File

@ -52,17 +52,20 @@ func Edit() http.HandlerFunc {
caption = r.FormValue("caption")
isExplicit = r.FormValue("explicit") == "true"
isGallery = r.FormValue("gallery") == "true"
visibility = r.FormValue("visibility")
visibility = models.PhotoVisibility(r.FormValue("visibility"))
// Profile pic fields
setProfilePic = r.FormValue("intent") == "profile-pic"
crop = pphoto.ParseCropCoords(r.FormValue("crop"))
// Are we GOING private?
goingPrivate = visibility == models.PhotoPrivate && visibility != photo.Visibility
)
photo.Caption = caption
photo.Explicit = isExplicit
photo.Gallery = isGallery
photo.Visibility = models.PhotoVisibility(visibility)
photo.Visibility = visibility
// Are we cropping ourselves a new profile pic?
log.Error("Profile pic? %+v and crop is: %+v", setProfilePic, crop)
@ -99,6 +102,12 @@ func Edit() http.HandlerFunc {
// Flash success.
session.Flash(w, r, "Photo settings updated!")
// If this picture has moved to Private, revoke any notification we gave about it before.
if goingPrivate {
log.Info("The picture is GOING PRIVATE, revoke any notifications about it")
models.RemoveNotification("photos", photo.ID)
}
// Whose photo gallery to redirect to? if admin editing a user's photo,
// go back to the owner's gallery instead of our own.
if photo.UserID != currentUser.ID {

View File

@ -131,6 +131,9 @@ func Upload() http.HandlerFunc {
user.Save()
}
// Notify all of our friends that we posted a new picture.
go notifyFriendsNewPhoto(p, user)
session.Flash(w, r, "Your photo has been uploaded successfully.")
templates.Redirect(w, "/photo/u/"+user.Username)
return
@ -142,3 +145,33 @@ func Upload() http.HandlerFunc {
}
})
}
// Create a notification for all our Friends about a new photo.
// Run in a background goroutine in case it takes a while.
func notifyFriendsNewPhoto(photo *models.Photo, currentUser *models.User) {
var friendIDs []uint64
// Who to notify?
if photo.Visibility == models.PhotoPrivate {
// Private grantees
friendIDs = models.PrivateGranteeUserIDs(currentUser.ID)
log.Info("Notify %d private grantees about the new photo by %s", len(friendIDs), currentUser.Username)
} else {
// Friends
friendIDs = models.FriendIDs(currentUser.ID)
log.Info("Notify %d friends about the new photo by %s", len(friendIDs), currentUser.Username)
}
for _, fid := range friendIDs {
notif := &models.Notification{
UserID: fid,
AboutUser: *currentUser,
Type: models.NotificationNewPhoto,
TableName: "photos",
TableID: photo.ID,
}
if err := models.CreateNotification(notif); err != nil {
log.Error("Couldn't notify user %d about %s's new photo: %s", fid, currentUser.Username, err)
}
}
}

View File

@ -39,12 +39,41 @@ const (
NotificationCertRejected = "cert_rejected"
NotificationCertApproved = "cert_approved"
NotificationPrivatePhoto = "private_photo"
NotificationNewPhoto = "new_photo"
NotificationCustom = "custom" // custom message pushed
)
// CreateNotification
func CreateNotification(n *Notification) error {
return DB.Create(n).Error
// Insert via raw SQL query, reasoning:
// the AboutUser relationship has gorm do way too much work:
// - Upsert the user profile photo
// - Upsert the user profile fields
// - Upsert the user row itself
// .. and if we notify all your friends, all these wasteful queries ran
// for every single notification created!
if n.AboutUserID == nil && n.AboutUser.ID > 0 {
n.AboutUserID = &n.AboutUser.ID
}
return DB.Exec(
`
INSERT INTO notifications
(user_id, about_user_id, type, read, table_name, table_id, message, link, created_at, updated_at)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`,
n.UserID,
n.AboutUserID,
n.Type,
false,
n.TableName,
n.TableID,
n.Message,
n.Link,
time.Now(),
time.Now(),
).Error
// return DB.Create(n).Error
}
// GetNotification by ID.

View File

@ -89,6 +89,19 @@ func PrivateGrantedUserIDs(userId uint64) []uint64 {
return userIDs
}
// PrivateGranteeUserIDs are the users whom WE have granted access to our photos (userId is the photo owners).
func PrivateGranteeUserIDs(userId uint64) []uint64 {
var (
ps = []*PrivatePhoto{}
userIDs = []uint64{}
)
DB.Where("source_user_id = ?", userId).Find(&ps)
for _, row := range ps {
userIDs = append(userIDs, row.TargetUserID)
}
return userIDs
}
/*
PaginatePrivatePhotoList views a user's list of private photo grants.

View File

@ -322,6 +322,23 @@
has granted you access to see their
<a href="{{.Link}}" class="has-text-private">private photos</a>!
</span>
{{else if eq .Type "new_photo"}}
<span class="icon">
{{if and $Body.Photo (eq $Body.Photo.Visibility "private")}}
<i class="fa fa-eye has-text-private"></i>
{{else}}
<i class="fa fa-image has-text-link"></i>
{{end}}
</span>
<span>
<a href="/u/{{.AboutUser.Username}}"><strong>{{.AboutUser.Username}}</strong></a>
has uploaded a new
{{if and $Body.Photo (eq $Body.Photo.Visibility "private")}}
<span class="has-text-private">private photo!</span>
{{else}}
photo!
{{end}}
</span>
{{else if eq .Type "cert_approved"}}
<span class="icon"><i class="fa fa-certificate has-text-success"></i></span>
<span>