Notifications about new photo uploads for your friends
This commit is contained in:
parent
eb913844f7
commit
f98b6b2806
|
@ -52,17 +52,20 @@ func Edit() http.HandlerFunc {
|
||||||
caption = r.FormValue("caption")
|
caption = r.FormValue("caption")
|
||||||
isExplicit = r.FormValue("explicit") == "true"
|
isExplicit = r.FormValue("explicit") == "true"
|
||||||
isGallery = r.FormValue("gallery") == "true"
|
isGallery = r.FormValue("gallery") == "true"
|
||||||
visibility = r.FormValue("visibility")
|
visibility = models.PhotoVisibility(r.FormValue("visibility"))
|
||||||
|
|
||||||
// Profile pic fields
|
// Profile pic fields
|
||||||
setProfilePic = r.FormValue("intent") == "profile-pic"
|
setProfilePic = r.FormValue("intent") == "profile-pic"
|
||||||
crop = pphoto.ParseCropCoords(r.FormValue("crop"))
|
crop = pphoto.ParseCropCoords(r.FormValue("crop"))
|
||||||
|
|
||||||
|
// Are we GOING private?
|
||||||
|
goingPrivate = visibility == models.PhotoPrivate && visibility != photo.Visibility
|
||||||
)
|
)
|
||||||
|
|
||||||
photo.Caption = caption
|
photo.Caption = caption
|
||||||
photo.Explicit = isExplicit
|
photo.Explicit = isExplicit
|
||||||
photo.Gallery = isGallery
|
photo.Gallery = isGallery
|
||||||
photo.Visibility = models.PhotoVisibility(visibility)
|
photo.Visibility = visibility
|
||||||
|
|
||||||
// Are we cropping ourselves a new profile pic?
|
// Are we cropping ourselves a new profile pic?
|
||||||
log.Error("Profile pic? %+v and crop is: %+v", setProfilePic, crop)
|
log.Error("Profile pic? %+v and crop is: %+v", setProfilePic, crop)
|
||||||
|
@ -99,6 +102,12 @@ func Edit() http.HandlerFunc {
|
||||||
// Flash success.
|
// Flash success.
|
||||||
session.Flash(w, r, "Photo settings updated!")
|
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,
|
// Whose photo gallery to redirect to? if admin editing a user's photo,
|
||||||
// go back to the owner's gallery instead of our own.
|
// go back to the owner's gallery instead of our own.
|
||||||
if photo.UserID != currentUser.ID {
|
if photo.UserID != currentUser.ID {
|
||||||
|
|
|
@ -131,6 +131,9 @@ func Upload() http.HandlerFunc {
|
||||||
user.Save()
|
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.")
|
session.Flash(w, r, "Your photo has been uploaded successfully.")
|
||||||
templates.Redirect(w, "/photo/u/"+user.Username)
|
templates.Redirect(w, "/photo/u/"+user.Username)
|
||||||
return
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -39,12 +39,41 @@ const (
|
||||||
NotificationCertRejected = "cert_rejected"
|
NotificationCertRejected = "cert_rejected"
|
||||||
NotificationCertApproved = "cert_approved"
|
NotificationCertApproved = "cert_approved"
|
||||||
NotificationPrivatePhoto = "private_photo"
|
NotificationPrivatePhoto = "private_photo"
|
||||||
|
NotificationNewPhoto = "new_photo"
|
||||||
NotificationCustom = "custom" // custom message pushed
|
NotificationCustom = "custom" // custom message pushed
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateNotification
|
// CreateNotification
|
||||||
func CreateNotification(n *Notification) error {
|
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.
|
// GetNotification by ID.
|
||||||
|
|
|
@ -89,6 +89,19 @@ func PrivateGrantedUserIDs(userId uint64) []uint64 {
|
||||||
return userIDs
|
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.
|
PaginatePrivatePhotoList views a user's list of private photo grants.
|
||||||
|
|
||||||
|
|
|
@ -322,6 +322,23 @@
|
||||||
has granted you access to see their
|
has granted you access to see their
|
||||||
<a href="{{.Link}}" class="has-text-private">private photos</a>!
|
<a href="{{.Link}}" class="has-text-private">private photos</a>!
|
||||||
</span>
|
</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"}}
|
{{else if eq .Type "cert_approved"}}
|
||||||
<span class="icon"><i class="fa fa-certificate has-text-success"></i></span>
|
<span class="icon"><i class="fa fa-certificate has-text-success"></i></span>
|
||||||
<span>
|
<span>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user