Site Gallery throttle

This commit is contained in:
Noah Petherbridge 2024-01-05 19:08:44 -08:00
parent 24ce39d306
commit 384638de09
6 changed files with 191 additions and 6 deletions

View File

@ -101,6 +101,13 @@ const (
// Min number of public photos for inner circle members to see the prompt to invite. // Min number of public photos for inner circle members to see the prompt to invite.
InnerCircleMinimumPublicPhotos = 5 InnerCircleMinimumPublicPhotos = 5
// Rate limit for too many Site Gallery pictures.
// Some users sign up and immediately max out their gallery and spam
// the Site Gallery page. These limits can ensure only a few Site Gallery
// pictures can be posted per day.
SiteGalleryRateLimitMax = 5
SiteGalleryRateLimitInterval = 24 * time.Hour
) )
// Forum settings // Forum settings

View File

@ -6,6 +6,7 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"code.nonshy.com/nonshy/website/pkg/config"
"code.nonshy.com/nonshy/website/pkg/log" "code.nonshy.com/nonshy/website/pkg/log"
"code.nonshy.com/nonshy/website/pkg/models" "code.nonshy.com/nonshy/website/pkg/models"
pphoto "code.nonshy.com/nonshy/website/pkg/photo" pphoto "code.nonshy.com/nonshy/website/pkg/photo"
@ -59,6 +60,9 @@ func Edit() http.HandlerFunc {
} }
} }
// Is the user throttled for Site Gallery photo uploads?
var SiteGalleryThrottled = models.IsSiteGalleryThrottled(currentUser, photo)
// Are we saving the changes? // Are we saving the changes?
if r.Method == http.MethodPost { if r.Method == http.MethodPost {
var ( var (
@ -76,6 +80,11 @@ func Edit() http.HandlerFunc {
goingCircle = visibility == models.PhotoInnerCircle && visibility != photo.Visibility goingCircle = visibility == models.PhotoInnerCircle && visibility != photo.Visibility
) )
// Respect the Site Gallery throttle in case the user is messing around.
if SiteGalleryThrottled {
isGallery = false
}
photo.Caption = caption photo.Caption = caption
photo.Explicit = isExplicit photo.Explicit = isExplicit
photo.Gallery = isGallery photo.Gallery = isGallery
@ -138,6 +147,8 @@ func Edit() http.HandlerFunc {
var vars = map[string]interface{}{ var vars = map[string]interface{}{
"EditPhoto": photo, "EditPhoto": photo,
"SiteGalleryThrottled": SiteGalleryThrottled,
"SiteGalleryThrottleLimit": config.SiteGalleryRateLimitMax,
} }
if err := tmpl.Execute(w, r, vars); err != nil { if err := tmpl.Execute(w, r, vars); err != nil {

View File

@ -7,6 +7,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"code.nonshy.com/nonshy/website/pkg/config"
"code.nonshy.com/nonshy/website/pkg/log" "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/photo" "code.nonshy.com/nonshy/website/pkg/photo"
@ -40,6 +41,10 @@ func Upload() http.HandlerFunc {
vars["PhotoCount"] = photoCount vars["PhotoCount"] = photoCount
vars["PhotoQuota"] = photoQuota vars["PhotoQuota"] = photoQuota
// Is the user throttled from sharing a Site Gallery photo too frequently?
vars["SiteGalleryThrottled"] = models.IsSiteGalleryThrottled(user, nil)
vars["SiteGalleryThrottleLimit"] = config.SiteGalleryRateLimitMax
// If they do not have a profile picture currently set (and are not uploading one now), // If they do not have a profile picture currently set (and are not uploading one now),
// the front-end should point this out to them. // the front-end should point this out to them.
if (user.ProfilePhotoID == nil || *user.ProfilePhotoID == 0) && vars["Intent"] != "profile_pic" { if (user.ProfilePhotoID == nil || *user.ProfilePhotoID == 0) && vars["Intent"] != "profile_pic" {
@ -63,6 +68,11 @@ func Upload() http.HandlerFunc {
confirm2 = r.PostFormValue("confirm2") == "true" confirm2 = r.PostFormValue("confirm2") == "true"
) )
// Enforce that they can not override the Site Gallery throttle.
if vars["SiteGalleryThrottled"].(bool) && isGallery {
isGallery = false
}
// Are they at quota already? // Are they at quota already?
if photoCount >= photoQuota { if photoCount >= photoQuota {
session.FlashError(w, r, "You have too many photos to upload a new one. Please delete a photo to make room for a new one.") session.FlashError(w, r, "You have too many photos to upload a new one. Please delete a photo to make room for a new one.")

View File

@ -170,6 +170,48 @@ func CountPhotos(userID uint64) int64 {
return count return count
} }
/*
IsSiteGalleryThrottled returns whether the user is throttled from marking additional pictures for the Site Gallery.
The thresholds are in pkg/config but the idea is a user can only upload (say) 5 Site Gallery photos within a
24 hour time span, so that new users who sign up and immediately max out their full gallery don't end up
spamming the Site Gallery for pages and pages.
If the user has too many recent Site Gallery pictures:
- Newly uploaded photos can NOT check the Gallery box.
- Editing any existing photo which is NOT in the Gallery: you can not mark the box either.
- Existing Gallery photos CAN be un-marked for the gallery, which (if it is one of the 5 recent
photos) may put the user below the threshold again.
If the user is on the Edit page for an existing photo, provide the Photo; otherwise leave it nil
if the user is uploading a new photo for the first time.
*/
func IsSiteGalleryThrottled(user *User, editPhoto *Photo) bool {
// If the editing photo is already in the gallery, allow the user to keep or remove it.
if editPhoto != nil && editPhoto.Gallery {
return false
}
var count = CountRecentGalleryPhotos(user, config.SiteGalleryRateLimitInterval)
log.Debug("IsSiteGalleryThrottled(%s): they have %d recent Gallery photos", user.Username, count)
return count >= config.SiteGalleryRateLimitMax
}
// CountRecentGalleryPhotos returns the count of recently uploaded Site Gallery photos for a user,
// within the past 24 hours, to rate limit spammy bulk uploads that will flood the gallery.
func CountRecentGalleryPhotos(user *User, duration time.Duration) (count int64) {
result := DB.Where(
"user_id = ? AND created_at >= ? AND gallery IS TRUE",
user.ID,
time.Now().Add(-duration),
).Model(&Photo{}).Count(&count)
if result.Error != nil {
log.Error("CountRecentGalleryPhotos(%d): %s", user.ID, result.Error)
}
return
}
// CountPhotosICanSee returns the number of photos on an account which can be seen by the given viewer. // CountPhotosICanSee returns the number of photos on an account which can be seen by the given viewer.
func CountPhotosICanSee(user *User, viewer *User) int64 { func CountPhotosICanSee(user *User, viewer *User) int64 {
// Visibility filters to query by. // Visibility filters to query by.

View File

@ -16,12 +16,12 @@
<!-- Table of Contents --> <!-- Table of Contents -->
<ul> <ul>
<li> <li>
<a href="#general-faqs">General FAQs</a> <span class="tag is-success">NEW June 26 2023</span> <a href="#general-faqs">General FAQs</a>
<ul> <ul>
<li><a href="#why">Why was this site built?</a></li> <li><a href="#why">Why was this site built?</a></li>
<li><a href="#whats-different">What makes this site <strong>different?</strong></a></li> <li><a href="#whats-different">What makes this site <strong>different?</strong></a></li>
<li><a href="#define-exhibitionist">What do you define as an <strong>"exhibitionist?"</strong></a> <span class="tag is-success">NEW June 26 2023</span></li> <li><a href="#define-exhibitionist">What do you define as an <strong>"exhibitionist?"</strong></a></li>
<li><a href="#why-sex-positive">Why does nonshy permit sexual content?</a> <span class="tag is-success">NEW June 26 2023</span></li> <li><a href="#why-sex-positive">Why does nonshy permit sexual content?</a></li>
</ul> </ul>
</li> </li>
<li> <li>
@ -39,6 +39,7 @@
<li><a href="#private-avatar">Can my <strong>Profile Picture be kept private?</strong></a></li> <li><a href="#private-avatar">Can my <strong>Profile Picture be kept private?</strong></a></li>
<li><a href="#profile-visibility">What are the <strong>visibility options</strong> for my profile page?</a></li> <li><a href="#profile-visibility">What are the <strong>visibility options</strong> for my profile page?</a></li>
<li><a href="#delete-messages">How do I delete direct messages (DMs)?</a></li> <li><a href="#delete-messages">How do I delete direct messages (DMs)?</a></li>
<li><a href="#blocking">How does <strong>blocking somebody</strong> work on nonshy?</a> <span class="tag is-success">NEW Jan 5 2024</span></li>
</ul> </ul>
</li> </li>
<li> <li>
@ -47,6 +48,7 @@
<li><a href="#nudes-required">Do I have to post my nudes here?</a></li> <li><a href="#nudes-required">Do I have to post my nudes here?</a></li>
<li><a href="#face-in-nudes">Do I have to include my face in my nudes?</a></li> <li><a href="#face-in-nudes">Do I have to include my face in my nudes?</a></li>
<li><a href="#site-gallery">What appears on the Site Gallery?</a></li> <li><a href="#site-gallery">What appears on the Site Gallery?</a></li>
<li><a href="#site-gallery-throttle">Why can't I feature my photo on the Site Gallery?</a> <span class="tag is-success">NEW Jan 5 2024</span></li>
<li><a href="#other-people">Can I include other people in my photos?</a></li> <li><a href="#other-people">Can I include other people in my photos?</a></li>
<li><a href="#define-explicit">What is considered "explicit" in photos?</a></li> <li><a href="#define-explicit">What is considered "explicit" in photos?</a></li>
<li><a href="#photoshop">Are digitally altered or 'photoshopped' pictures okay?</a></li> <li><a href="#photoshop">Are digitally altered or 'photoshopped' pictures okay?</a></li>
@ -429,6 +431,52 @@
at all. at all.
</p> </p>
<h3 id="blocking">How does blocking somebody work on nonshy?</h3>
<p>
If somebody on {{PrettyTitle}} is bothering you or you just do not wish to see their
presence or content around the website anymore, you may "Block" them by going to their profile
page and clicking on the Block button.
</p>
<p>
When you block somebody, {{PrettyTitle}} draws a <strong>hard line</strong> between your
two accounts and will make it so that you two <strong>do not see each other</strong> anywhere
on the website:
</p>
<ul>
<li>
You will not see them on the Member Directory, you will not see them in the Forums
(their posts and comments will be hidden), you will not see them in comment threads
on peoples' photos, or in their "Likes" lists, or anywhere.
</li>
<li>
If you had any Direct Messages with them in the past: your conversation threads will
be hidden from view on both sides. If you unblock them later, you will be able to see
your old conversation threads again.
</li>
<li>
On the <strong>chat room:</strong> you will not see each other in the "Who's Online"
list and you won't see any messages sent by each other in chat.
</li>
<li>
This block applies in <strong>both directions:</strong> you will not see them, and they
will likewise not see you either.
</li>
</ul>
<p>
The idea is that if you block somebody, it should look as though they may have just deleted their
{{PrettyTitle}} account completely and you should not see them anymore and they should not see
you either.
</p>
<p>
If you find any corner of the site where this fails to happen (and you see somebody who you have
blocked), please <a href="/contact?intent=report&subject=bug">report it as a bug</a> to be fixed.
</p>
<h1 id="photo-faqs">Photo FAQs</h1> <h1 id="photo-faqs">Photo FAQs</h1>
<h3 id="nudes-required">Do I have to post my nudes here?</h3> <h3 id="nudes-required">Do I have to post my nudes here?</h3>
@ -484,6 +532,54 @@
the Gallery -- it will then only appear on your profile page. the Gallery -- it will then only appear on your profile page.
</p> </p>
<h3 id="site-gallery-throttle">Why can't I feature my photo on the Site Gallery?</h3>
<p>
In January 2024 we have added a rate limit on how frequently you can upload a new photo
and have it appear on the site-wide Photo Gallery in order to cut down on "spam" when a
new member would sign up and immediately upload all 100 of their photos to their gallery
page.
</p>
<p>
We don't want the Site Gallery to be dominated by large swaths of only <em>one person's</em>
photos that go on for pages and pages, so you may only feature up to
<strong>5 photos per day</strong> on the Site Gallery.
When you have 5 or more photos, uploaded within the last 24 hours and marked to share with the
Site Gallery, you will not be able to add additional photos to the gallery until you
wait a day <strong>OR</strong> edit one of those recent photos to remove it from
the gallery.
</p>
<p>
If you have been throttled from sharing new Site Gallery photos, your options are:
</p>
<ul>
<li>
To come back tomorrow and upload your new photo if you want it featured
on the Site Gallery.
</li>
<li>
To edit one of your <strong>5 most recent Site Gallery</strong> photos and un-check
the Gallery box: this may free up room so that your new upload can be shared with
the Site Gallery if you <em>really</em> want to feature it now.
</li>
<li>
To upload it anyway to your personal gallery, even though it won't be featured
on the site-wide gallery. If you <em>want</em> to upload all 100 of your nudes as
soon as you get your {{PrettyTitle}} account certified, go ahead! You just aren't
allowed to spam the Site Gallery with all your uploads all at once.
</li>
</ul>
<p>
<strong>Our recommendation:</strong> take it slow! Share a few pictures per day on your gallery
until you eventually fill it out. This is also a better way to get engagement on your photos:
your friends are more likely to "Like" and comment on your photos if you drip feed them slowly
vs. if you upload your 100 photos all at once.
</p>
<h3 id="other-people">Can I include other people in my photos?</h3> <h3 id="other-people">Can I include other people in my photos?</h3>
<p> <p>

View File

@ -322,9 +322,27 @@
<input type="checkbox" <input type="checkbox"
name="gallery" name="gallery"
value="true" value="true"
{{if or .EditPhoto.Gallery (not .EditPhoto)}}checked{{end}}> {{if and (or .EditPhoto.Gallery (not .EditPhoto)) (not .SiteGalleryThrottled)}}checked{{end}}
{{if .SiteGalleryThrottled}}disabled{{end}}>
{{if .SiteGalleryThrottled}}<del>{{end}}
Show this photo in the site-wide Photo Gallery Show this photo in the site-wide Photo Gallery
{{if .SiteGalleryThrottled}}</del>{{end}}
</label> </label>
{{if .SiteGalleryThrottled}}
<p class="help has-text-warning-dark">
<i class="fa fa-exclamation-triangle"></i>
You have shared too many photos with the Site Gallery recently!<br><br>
We currently limit members to featuring <strong>{{.SiteGalleryThrottleLimit}} photos</strong>
on the Site Gallery per day, so that one member doesn't dominate page after
page of the gallery by uploading <em>all</em> of their pictures at once.
<a href="/faq#site-gallery-throttle" target="_blank">Learn more <i class="fa fa-external-link"></i></a>
<br><br>
You may still upload all the photos you like to <em>your</em> gallery, but new ones can not be featured
on the Site Gallery until you have waited 24 hours. You MAY "edit" your recently posted photos
and un-check the Site Gallery box if you <em>really</em> want this one to be featured now.
</p>
{{else}}
<p class="help"> <p class="help">
Leave this box checked and your photo can appear in the site's Photo Gallery Leave this box checked and your photo can appear in the site's Photo Gallery
page. Mainly your <strong class="has-text-link">Public</strong> photos will appear page. Mainly your <strong class="has-text-link">Public</strong> photos will appear
@ -334,6 +352,7 @@
the gallery to users whom you have granted access. If this is undesirable, the gallery to users whom you have granted access. If this is undesirable,
un-check the Gallery box to skip the Site Gallery. un-check the Gallery box to skip the Site Gallery.
</p> </p>
{{end}}
</div> </div>
<div class="field mb-5"> <div class="field mb-5">