Blur Explicit GIFs + Forum Improvements

* Fix a bug where explicit GIF videos weren't blurring when the user
  wanted them to be blurred.
* Make some improvements to the forums:
  * Polls will now remember the Expires setting while you are previewing
    and revising your original post.
  * Add 14 day and 30 day Expire options for polls.
  * Add disclaimer warnings above the Photo Attachment field when the
    current forum or thread isn't marked for Explicit content.
This commit is contained in:
Noah Petherbridge 2024-11-28 11:21:06 -08:00
parent f7e5e36576
commit 688d2e0baa
7 changed files with 160 additions and 42 deletions

View File

@ -165,6 +165,50 @@ var (
"Anything Goes",
}
// Forum Poll expiration options.
PollExpires = []Option{
{
Label: "Never",
Value: "0",
},
{
Label: "1 Day",
Value: "1",
},
{
Label: "2 Days",
Value: "2",
},
{
Label: "3 Days",
Value: "3",
},
{
Label: "4 Days",
Value: "4",
},
{
Label: "5 Days",
Value: "5",
},
{
Label: "6 Days",
Value: "6",
},
{
Label: "7 Days",
Value: "7",
},
{
Label: "2 Weeks",
Value: "14",
},
{
Label: "1 Month (30 days)",
Value: "30",
},
}
// Keywords that appear in a DM that make it likely spam.
DirectMessageSpamKeywords = []*regexp.Regexp{
regexp.MustCompile(`\b(telegram|whats\s*app|signal|kik|session)\b`),

View File

@ -47,6 +47,10 @@ func NewPost() http.HandlerFunc {
// well (pinned, explicit, noreply)
isOriginalComment bool
// If neither the forum nor thread are explicit, show a hint to the user not to
// share an explicit photo in their reply.
explicitPhotoAllowed bool
// Polls
pollOptions = []string{}
pollExpires = 3
@ -87,6 +91,11 @@ func NewPost() http.HandlerFunc {
}
}
// Would an explicit photo attachment be allowed?
if forum.Explicit || (thread != nil && thread.Explicit) {
explicitPhotoAllowed = true
}
// If the current user can moderate the forum thread, e.g. edit or delete posts.
// Admins can edit always, user owners of forums can only delete.
var canModerate = currentUser.HasAdminScope(config.ScopeForumModerator) ||
@ -493,13 +502,14 @@ func NewPost() http.HandlerFunc {
}
var vars = map[string]interface{}{
"Forum": forum,
"Thread": thread,
"Intent": intent,
"PostTitle": title,
"EditCommentID": editCommentID,
"EditThreadSettings": isOriginalComment,
"Message": message,
"Forum": forum,
"Thread": thread,
"Intent": intent,
"PostTitle": title,
"EditCommentID": editCommentID,
"EditThreadSettings": isOriginalComment,
"ExplicitPhotoAllowed": explicitPhotoAllowed,
"Message": message,
// Thread settings (for editing the original comment esp.)
"IsPinned": isPinned,
@ -507,7 +517,9 @@ func NewPost() http.HandlerFunc {
"IsNoReply": isNoReply,
// Polls
"PollOptions": pollOptions,
"PollOptions": pollOptions,
"PollExpires": pollExpires,
"PollExpiresOptions": config.PollExpires,
// Attached photo.
"CommentPhoto": commentPhoto,

View File

@ -20,6 +20,10 @@ func Thread() http.HandlerFunc {
idStr = r.PathValue("id")
forum *models.Forum
thread *models.Thread
// If neither the forum nor thread are explicit, show a hint to the user not to
// share an explicit photo in their reply.
explicitPhotoAllowed bool
)
if idStr == "" {
@ -61,6 +65,11 @@ func Thread() http.HandlerFunc {
// e.g. can we delete threads and posts, not edit them)
var canModerate = forum.CanBeModeratedBy(currentUser)
// Would an explicit photo attachment be allowed?
if forum.Explicit || thread.Explicit {
explicitPhotoAllowed = true
}
// Ping the view count on this thread.
if err := thread.View(currentUser.ID); err != nil {
log.Error("Couldn't ping view count on thread %d: %s", thread.ID, err)
@ -105,15 +114,16 @@ func Thread() http.HandlerFunc {
}()
var vars = map[string]interface{}{
"Forum": forum,
"Thread": thread,
"Comments": comments,
"LikeMap": commentLikeMap,
"PhotoMap": photos,
"Pager": pager,
"CanModerate": canModerate,
"IsSubscribed": isSubscribed,
"IsForumSubscribed": models.IsForumSubscribed(currentUser, forum),
"Forum": forum,
"Thread": thread,
"Comments": comments,
"LikeMap": commentLikeMap,
"PhotoMap": photos,
"Pager": pager,
"CanModerate": canModerate,
"IsSubscribed": isSubscribed,
"IsForumSubscribed": models.IsForumSubscribed(currentUser, forum),
"ExplicitPhotoAllowed": explicitPhotoAllowed,
}
if err := tmpl.Execute(w, r, vars); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)

View File

@ -38,10 +38,13 @@ func TemplateFuncs(r *http.Request) template.FuncMap {
"ToMarkdown": ToMarkdown,
"ToJSON": ToJSON,
"ToHTML": ToHTML,
"PhotoURL": PhotoURL(r),
"VisibleAvatarURL": photo.VisibleAvatarURL,
"Now": time.Now,
"RunTime": RunTime,
"ToString": func(v interface{}) string {
return fmt.Sprintf("%v", v)
},
"PhotoURL": PhotoURL(r),
"VisibleAvatarURL": photo.VisibleAvatarURL,
"Now": time.Now,
"RunTime": RunTime,
"PrettyTitle": func() template.HTML {
return template.HTML(fmt.Sprintf(
`<strong style="color: #0077FF">non</strong>` +

View File

@ -28,6 +28,8 @@
</div>
</section>
{{$Root := .}}
<div class="block p-4">
<div class="columns is-centered">
<div class="column is-half">
@ -83,7 +85,7 @@
{{if and (not .EditCommentID) (not .Thread)}}
<div class="field block">
<label for="message" class="label">Poll <span class="tag is-success">NEW!</span></label>
<label for="message" class="label">Poll</label>
<div v-if="pollVisible">
<!-- MultipleChoice option -->
<div class="mb-2">
@ -134,14 +136,9 @@
<div class="select is-small is-fullwidth">
<select v-model="expires"
name="poll_expires">
<option :value="0">Never</option>
<option :value="1">1 Day</option>
<option :value="2">2 Days</option>
<option :value="3">3 Days</option>
<option :value="4">4 Days</option>
<option :value="5">5 Days</option>
<option :value="6">6 Days</option>
<option :value="7">7 Days</option>
{{range .PollExpiresOptions}}
<option :value="{{.Value}}">{{.Label}}</option>
{{end}}
</select>
</div>
</div>
@ -173,6 +170,33 @@
<div class="field block">
<label class="label">Photo Attachment</label>
<!-- Non-explicit Photo Notice -->
{{if not .ExplicitPhotoAllowed}}
<p class="help mb-4">
<!-- If NEW thread on a non-explicit forum -->
{{if not .Thread}}
<strong class="has-text-danger">
<i class="fa fa-exclamation-triangle mr-1"></i>
Explicit Photo Notice:
</strong>
The forum you are posting to isn't marked as Explicit. If you are going to share
an <a href="/faq#define-explicit">Explicit</a> photo, <strong>please also mark this thread
as Explicit</strong> using the checkbox below!
{{else}}
<strong class="has-text-danger">
<i class="fa fa-ban mr-1"></i>
No Explicit Photos:
</strong>
This {{if not .Thread}}forum{{else}}thread{{end}} is not marked to accept Explicit
photos being shared. If you are going to upload a nude picture, <strong>please make sure</strong>
it is not an <a href="/faq#define-explicit">Explicit</a> photo. Thanks!
{{end}}
</p>
{{end}}
<div class="file has-name is-fullwidth">
<label class="file-label">
<input class="file-input" type="file"
@ -238,6 +262,13 @@
{{if .IsExplicit}}checked{{end}}>
Mark as Explicit (NSFW)
</label>
{{if not .Forum.Explicit}}
<p class="help">
The forum you are posting this in is not marked as Explicit, however the occasional
Explicit thread is allowed as long as it is correctly tagged. <strong>Please</strong>
check this box if the text or attached photos on this thread will be sexual in nature!
</p>
{{end}}
</div>
{{end}}
@ -376,7 +407,7 @@
{value: ""},
{value: ""},
],
expires: 3, // days
expires: parseInt({{.PollExpires}}), // days
answersLimit: 100,
}
},

View File

@ -264,9 +264,14 @@
{{else}}
<!-- GIF video? -->
{{if HasSuffix .Filename ".mp4"}}
<video autoplay loop controls controlsList="nodownload" playsinline>
<source src="{{PhotoURL .Filename}}" type="video/mp4">
</video>
<div class="mt-4 is-clipped">
<video loop controls controlsList="nodownload" playsinline
{{if and (or $Root.Forum.Explicit $Root.Thread.Explicit) (eq ($Root.CurrentUser.GetProfileField "blur_explicit") "true")}} class="blurred-explicit"{{end}}
{{if and (not (eq ($Root.CurrentUser.GetProfileField "blur_explicit") "true")) (not (eq ($Root.CurrentUser.GetProfileField "autoplay_gif") "false"))}}autoplay{{end}}
>
<source src="{{PhotoURL .Filename}}" type="video/mp4">
</video>
</div>
{{else}}
<div class="mt-4 is-clipped">
<img src="{{PhotoURL .Filename}}" loading="lazy"{{if and (or $Root.Forum.Explicit $Root.Thread.Explicit) (eq ($Root.CurrentUser.GetProfileField "blur_explicit") "true")}} class="blurred-explicit"{{end}}>
@ -485,6 +490,21 @@
</div>
<label class="label">Photo Attachment</label>
<!-- Non-explicit Photo Notice -->
{{if not .ExplicitPhotoAllowed}}
<p class="help mb-4">
<strong class="has-text-danger">
<i class="fa fa-ban mr-1"></i>
No Explicit Photos:
</strong>
This {{if not .Thread}}forum{{else}}thread{{end}} is not marked to accept Explicit
photos being shared. If you are going to upload a nude picture, <strong>please make sure</strong>
it is not an <a href="/faq#define-explicit">Explicit</a> photo. Thanks!
</p>
{{end}}
<div class="file has-name is-fullwidth">
<label class="file-label">
<input class="file-input" type="file"

View File

@ -553,12 +553,11 @@
<!-- GIF video? -->
{{if HasSuffix .Filename ".mp4"}}
<video loop controls controlsList="nodownload" playsinline
class="js-modal-trigger"
class="js-modal-trigger{{if BlurExplicit .}} blurred-explicit{{end}}"
data-url="{{PhotoURL .Filename}}" data-photo-id="{{.ID}}"
{{if .AltText}}title="{{.AltText}}"{{end}}
{{if BlurExplicit .}}class="blurred-explicit"
{{else if (not (eq ($Root.CurrentUser.GetProfileField "autoplay_gif") "false"))}}autoplay
{{end}}>
{{if and (not (BlurExplicit .)) (not (eq ($Root.CurrentUser.GetProfileField "autoplay_gif") "false"))}}autoplay{{end}}
>
<source src="{{PhotoURL .Filename}}" type="video/mp4">
</video>
{{else}}
@ -680,12 +679,11 @@
<!-- GIF video? -->
{{if HasSuffix .Filename ".mp4"}}
<video loop controls controlsList="nodownload" playsinline
class="js-modal-trigger"
class="js-modal-trigger{{if BlurExplicit .}} blurred-explicit{{end}}"
data-url="{{PhotoURL .Filename}}" data-photo-id="{{.ID}}"
{{if .AltText}}title="{{.AltText}}"{{end}}
{{if BlurExplicit .}}class="blurred-explicit"
{{else if (not (eq ($Root.CurrentUser.GetProfileField "autoplay_gif") "false"))}}autoplay
{{end}}>
{{if and (not (BlurExplicit .)) (not (eq ($Root.CurrentUser.GetProfileField "autoplay_gif") "false"))}}autoplay{{end}}
>
<source src="{{PhotoURL .Filename}}" type="video/mp4">
</video>
{{else}}