666d3105b7
* On user profile pages and gallery: the total photo count for the user will only include photos that the viewer can actually see (taking into account friendship and private grants), so that users won't harass each other to see the additional photos that aren't visible to them. * On the member directory search: the photo counts will only show public photos on their page for now, and may be fewer than the number of photos the current user could actually see. * Blocklist: you can now manually add a user by username to your block list. So if somebody blocked you on the site and you want to block them back, there is a way to do this. * Friends: you can now directly unfriend someone from their profile page by clicking on the "Friends" button. You get a confirmation popup before the remove friend action goes through. * Bugfix: when viewing a user's gallery, you were able to see their Friends-only photos if they granted you their Private photo access, even if you were not their friend. * Bugfix: when uploading a new private photo, instead of notifying everybody you granted access to your privates it will only notify if they are also on your friend list.
166 lines
5.3 KiB
Go
166 lines
5.3 KiB
Go
package photo
|
|
|
|
import (
|
|
"net/http"
|
|
"regexp"
|
|
|
|
"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/session"
|
|
"code.nonshy.com/nonshy/website/pkg/templates"
|
|
)
|
|
|
|
var UserPhotosRegexp = regexp.MustCompile(`^/photo/u/([^@]+?)$`)
|
|
|
|
// UserPhotos controller (/photo/u/:username) to view a user's gallery or manage if it's yourself.
|
|
func UserPhotos() http.HandlerFunc {
|
|
tmpl := templates.Must("photo/gallery.html")
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
// Query params.
|
|
var (
|
|
viewStyle = r.FormValue("view") // cards (default), full
|
|
)
|
|
if viewStyle != "full" {
|
|
viewStyle = "cards"
|
|
}
|
|
|
|
// Parse the username out of the URL parameters.
|
|
var username string
|
|
m := UserPhotosRegexp.FindStringSubmatch(r.URL.Path)
|
|
if m != nil {
|
|
username = m[1]
|
|
}
|
|
|
|
// Find this user.
|
|
user, err := models.FindUser(username)
|
|
if err != nil {
|
|
templates.NotFoundPage(w, r)
|
|
return
|
|
}
|
|
|
|
// Load the current user in case they are viewing their own page.
|
|
currentUser, err := session.CurrentUser(r)
|
|
if err != nil {
|
|
session.FlashError(w, r, "Unexpected error: couldn't get CurrentUser")
|
|
}
|
|
var (
|
|
isOwnPhotos = currentUser.ID == user.ID
|
|
isShy = currentUser.IsShy()
|
|
isShyFrom = !isOwnPhotos && (currentUser.IsShyFrom(user) || (isShy && !models.AreFriends(currentUser.ID, user.ID)))
|
|
)
|
|
|
|
// Bail early if we are shy from this user.
|
|
if isShy && isShyFrom {
|
|
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": []*models.Photo{},
|
|
"PhotoCount": models.CountPhotos(user.ID),
|
|
"Pager": models.Pagination{},
|
|
}
|
|
|
|
if err := tmpl.Execute(w, r, vars); err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
}
|
|
return
|
|
}
|
|
|
|
// Is either one blocking?
|
|
if models.IsBlocking(currentUser.ID, user.ID) && !currentUser.IsAdmin {
|
|
templates.NotFoundPage(w, r)
|
|
return
|
|
}
|
|
|
|
// Is this user private and we're not friends?
|
|
var (
|
|
areFriends = models.AreFriends(user.ID, currentUser.ID)
|
|
isPrivate = user.Visibility == models.UserVisibilityPrivate && !areFriends
|
|
)
|
|
if isPrivate && !currentUser.IsAdmin && !isOwnPhotos {
|
|
session.FlashError(w, r, "This user's profile page and photo gallery are private.")
|
|
templates.Redirect(w, "/u/"+user.Username)
|
|
return
|
|
}
|
|
|
|
// Has this user granted access to see their privates?
|
|
var (
|
|
isGrantee = models.IsPrivateUnlocked(user.ID, currentUser.ID) // THEY have granted US access
|
|
isGranted = models.IsPrivateUnlocked(currentUser.ID, user.ID) // WE have granted THEM access
|
|
)
|
|
|
|
// What set of visibilities to query?
|
|
visibility := []models.PhotoVisibility{models.PhotoPublic}
|
|
if isOwnPhotos || isGrantee || currentUser.HasAdminScope(config.ScopePhotoModerator) {
|
|
visibility = append(visibility, models.PhotoPrivate)
|
|
}
|
|
if models.AreFriends(user.ID, currentUser.ID) {
|
|
visibility = append(visibility, models.PhotoFriends)
|
|
}
|
|
|
|
// Inner circle photos.
|
|
if currentUser.IsInnerCircle() {
|
|
visibility = append(visibility, models.PhotoInnerCircle)
|
|
}
|
|
|
|
// Explicit photo filter?
|
|
explicit := currentUser.Explicit
|
|
if isOwnPhotos {
|
|
explicit = true
|
|
}
|
|
|
|
// Get the page of photos.
|
|
pager := &models.Pagination{
|
|
Page: 1,
|
|
PerPage: config.PageSizeUserGallery,
|
|
Sort: "created_at desc",
|
|
}
|
|
pager.ParsePage(r)
|
|
photos, err := models.PaginateUserPhotos(user.ID, visibility, explicit, pager)
|
|
if err != nil {
|
|
log.Error("PaginateUserPhotos(%s): %s", user.Username, err)
|
|
}
|
|
|
|
// Get the count of explicit photos if we are not viewing explicit photos.
|
|
var explicitCount int64
|
|
if !explicit {
|
|
explicitCount, _ = models.CountExplicitPhotos(user.ID, visibility)
|
|
}
|
|
|
|
// Get Likes information about these photos.
|
|
var photoIDs = []uint64{}
|
|
for _, p := range photos {
|
|
photoIDs = append(photoIDs, p.ID)
|
|
}
|
|
likeMap := models.MapLikes(currentUser, "photos", photoIDs)
|
|
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.CountPhotosICanSee(user, currentUser),
|
|
"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 {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
})
|
|
}
|