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:
parent
f7e5e36576
commit
688d2e0baa
|
@ -165,6 +165,50 @@ var (
|
||||||
"Anything Goes",
|
"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.
|
// Keywords that appear in a DM that make it likely spam.
|
||||||
DirectMessageSpamKeywords = []*regexp.Regexp{
|
DirectMessageSpamKeywords = []*regexp.Regexp{
|
||||||
regexp.MustCompile(`\b(telegram|whats\s*app|signal|kik|session)\b`),
|
regexp.MustCompile(`\b(telegram|whats\s*app|signal|kik|session)\b`),
|
||||||
|
|
|
@ -47,6 +47,10 @@ func NewPost() http.HandlerFunc {
|
||||||
// well (pinned, explicit, noreply)
|
// well (pinned, explicit, noreply)
|
||||||
isOriginalComment bool
|
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
|
// Polls
|
||||||
pollOptions = []string{}
|
pollOptions = []string{}
|
||||||
pollExpires = 3
|
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.
|
// 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.
|
// Admins can edit always, user owners of forums can only delete.
|
||||||
var canModerate = currentUser.HasAdminScope(config.ScopeForumModerator) ||
|
var canModerate = currentUser.HasAdminScope(config.ScopeForumModerator) ||
|
||||||
|
@ -493,13 +502,14 @@ func NewPost() http.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
var vars = map[string]interface{}{
|
var vars = map[string]interface{}{
|
||||||
"Forum": forum,
|
"Forum": forum,
|
||||||
"Thread": thread,
|
"Thread": thread,
|
||||||
"Intent": intent,
|
"Intent": intent,
|
||||||
"PostTitle": title,
|
"PostTitle": title,
|
||||||
"EditCommentID": editCommentID,
|
"EditCommentID": editCommentID,
|
||||||
"EditThreadSettings": isOriginalComment,
|
"EditThreadSettings": isOriginalComment,
|
||||||
"Message": message,
|
"ExplicitPhotoAllowed": explicitPhotoAllowed,
|
||||||
|
"Message": message,
|
||||||
|
|
||||||
// Thread settings (for editing the original comment esp.)
|
// Thread settings (for editing the original comment esp.)
|
||||||
"IsPinned": isPinned,
|
"IsPinned": isPinned,
|
||||||
|
@ -507,7 +517,9 @@ func NewPost() http.HandlerFunc {
|
||||||
"IsNoReply": isNoReply,
|
"IsNoReply": isNoReply,
|
||||||
|
|
||||||
// Polls
|
// Polls
|
||||||
"PollOptions": pollOptions,
|
"PollOptions": pollOptions,
|
||||||
|
"PollExpires": pollExpires,
|
||||||
|
"PollExpiresOptions": config.PollExpires,
|
||||||
|
|
||||||
// Attached photo.
|
// Attached photo.
|
||||||
"CommentPhoto": commentPhoto,
|
"CommentPhoto": commentPhoto,
|
||||||
|
|
|
@ -20,6 +20,10 @@ func Thread() http.HandlerFunc {
|
||||||
idStr = r.PathValue("id")
|
idStr = r.PathValue("id")
|
||||||
forum *models.Forum
|
forum *models.Forum
|
||||||
thread *models.Thread
|
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 == "" {
|
if idStr == "" {
|
||||||
|
@ -61,6 +65,11 @@ func Thread() http.HandlerFunc {
|
||||||
// e.g. can we delete threads and posts, not edit them)
|
// e.g. can we delete threads and posts, not edit them)
|
||||||
var canModerate = forum.CanBeModeratedBy(currentUser)
|
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.
|
// Ping the view count on this thread.
|
||||||
if err := thread.View(currentUser.ID); err != nil {
|
if err := thread.View(currentUser.ID); err != nil {
|
||||||
log.Error("Couldn't ping view count on thread %d: %s", thread.ID, err)
|
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{}{
|
var vars = map[string]interface{}{
|
||||||
"Forum": forum,
|
"Forum": forum,
|
||||||
"Thread": thread,
|
"Thread": thread,
|
||||||
"Comments": comments,
|
"Comments": comments,
|
||||||
"LikeMap": commentLikeMap,
|
"LikeMap": commentLikeMap,
|
||||||
"PhotoMap": photos,
|
"PhotoMap": photos,
|
||||||
"Pager": pager,
|
"Pager": pager,
|
||||||
"CanModerate": canModerate,
|
"CanModerate": canModerate,
|
||||||
"IsSubscribed": isSubscribed,
|
"IsSubscribed": isSubscribed,
|
||||||
"IsForumSubscribed": models.IsForumSubscribed(currentUser, forum),
|
"IsForumSubscribed": models.IsForumSubscribed(currentUser, forum),
|
||||||
|
"ExplicitPhotoAllowed": explicitPhotoAllowed,
|
||||||
}
|
}
|
||||||
if err := tmpl.Execute(w, r, vars); err != nil {
|
if err := tmpl.Execute(w, r, vars); err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
|
|
@ -38,10 +38,13 @@ func TemplateFuncs(r *http.Request) template.FuncMap {
|
||||||
"ToMarkdown": ToMarkdown,
|
"ToMarkdown": ToMarkdown,
|
||||||
"ToJSON": ToJSON,
|
"ToJSON": ToJSON,
|
||||||
"ToHTML": ToHTML,
|
"ToHTML": ToHTML,
|
||||||
"PhotoURL": PhotoURL(r),
|
"ToString": func(v interface{}) string {
|
||||||
"VisibleAvatarURL": photo.VisibleAvatarURL,
|
return fmt.Sprintf("%v", v)
|
||||||
"Now": time.Now,
|
},
|
||||||
"RunTime": RunTime,
|
"PhotoURL": PhotoURL(r),
|
||||||
|
"VisibleAvatarURL": photo.VisibleAvatarURL,
|
||||||
|
"Now": time.Now,
|
||||||
|
"RunTime": RunTime,
|
||||||
"PrettyTitle": func() template.HTML {
|
"PrettyTitle": func() template.HTML {
|
||||||
return template.HTML(fmt.Sprintf(
|
return template.HTML(fmt.Sprintf(
|
||||||
`<strong style="color: #0077FF">non</strong>` +
|
`<strong style="color: #0077FF">non</strong>` +
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
{{$Root := .}}
|
||||||
|
|
||||||
<div class="block p-4">
|
<div class="block p-4">
|
||||||
<div class="columns is-centered">
|
<div class="columns is-centered">
|
||||||
<div class="column is-half">
|
<div class="column is-half">
|
||||||
|
@ -83,7 +85,7 @@
|
||||||
|
|
||||||
{{if and (not .EditCommentID) (not .Thread)}}
|
{{if and (not .EditCommentID) (not .Thread)}}
|
||||||
<div class="field block">
|
<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">
|
<div v-if="pollVisible">
|
||||||
<!-- MultipleChoice option -->
|
<!-- MultipleChoice option -->
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
|
@ -134,14 +136,9 @@
|
||||||
<div class="select is-small is-fullwidth">
|
<div class="select is-small is-fullwidth">
|
||||||
<select v-model="expires"
|
<select v-model="expires"
|
||||||
name="poll_expires">
|
name="poll_expires">
|
||||||
<option :value="0">Never</option>
|
{{range .PollExpiresOptions}}
|
||||||
<option :value="1">1 Day</option>
|
<option :value="{{.Value}}">{{.Label}}</option>
|
||||||
<option :value="2">2 Days</option>
|
{{end}}
|
||||||
<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>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -173,6 +170,33 @@
|
||||||
|
|
||||||
<div class="field block">
|
<div class="field block">
|
||||||
<label class="label">Photo Attachment</label>
|
<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">
|
<div class="file has-name is-fullwidth">
|
||||||
<label class="file-label">
|
<label class="file-label">
|
||||||
<input class="file-input" type="file"
|
<input class="file-input" type="file"
|
||||||
|
@ -238,6 +262,13 @@
|
||||||
{{if .IsExplicit}}checked{{end}}>
|
{{if .IsExplicit}}checked{{end}}>
|
||||||
Mark as Explicit (NSFW)
|
Mark as Explicit (NSFW)
|
||||||
</label>
|
</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>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
@ -376,7 +407,7 @@
|
||||||
{value: ""},
|
{value: ""},
|
||||||
{value: ""},
|
{value: ""},
|
||||||
],
|
],
|
||||||
expires: 3, // days
|
expires: parseInt({{.PollExpires}}), // days
|
||||||
answersLimit: 100,
|
answersLimit: 100,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -264,9 +264,14 @@
|
||||||
{{else}}
|
{{else}}
|
||||||
<!-- GIF video? -->
|
<!-- GIF video? -->
|
||||||
{{if HasSuffix .Filename ".mp4"}}
|
{{if HasSuffix .Filename ".mp4"}}
|
||||||
<video autoplay loop controls controlsList="nodownload" playsinline>
|
<div class="mt-4 is-clipped">
|
||||||
<source src="{{PhotoURL .Filename}}" type="video/mp4">
|
<video loop controls controlsList="nodownload" playsinline
|
||||||
</video>
|
{{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}}
|
{{else}}
|
||||||
<div class="mt-4 is-clipped">
|
<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}}>
|
<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>
|
</div>
|
||||||
|
|
||||||
<label class="label">Photo Attachment</label>
|
<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">
|
<div class="file has-name is-fullwidth">
|
||||||
<label class="file-label">
|
<label class="file-label">
|
||||||
<input class="file-input" type="file"
|
<input class="file-input" type="file"
|
||||||
|
|
|
@ -553,12 +553,11 @@
|
||||||
<!-- GIF video? -->
|
<!-- GIF video? -->
|
||||||
{{if HasSuffix .Filename ".mp4"}}
|
{{if HasSuffix .Filename ".mp4"}}
|
||||||
<video loop controls controlsList="nodownload" playsinline
|
<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}}"
|
data-url="{{PhotoURL .Filename}}" data-photo-id="{{.ID}}"
|
||||||
{{if .AltText}}title="{{.AltText}}"{{end}}
|
{{if .AltText}}title="{{.AltText}}"{{end}}
|
||||||
{{if BlurExplicit .}}class="blurred-explicit"
|
{{if and (not (BlurExplicit .)) (not (eq ($Root.CurrentUser.GetProfileField "autoplay_gif") "false"))}}autoplay{{end}}
|
||||||
{{else if (not (eq ($Root.CurrentUser.GetProfileField "autoplay_gif") "false"))}}autoplay
|
>
|
||||||
{{end}}>
|
|
||||||
<source src="{{PhotoURL .Filename}}" type="video/mp4">
|
<source src="{{PhotoURL .Filename}}" type="video/mp4">
|
||||||
</video>
|
</video>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
@ -680,12 +679,11 @@
|
||||||
<!-- GIF video? -->
|
<!-- GIF video? -->
|
||||||
{{if HasSuffix .Filename ".mp4"}}
|
{{if HasSuffix .Filename ".mp4"}}
|
||||||
<video loop controls controlsList="nodownload" playsinline
|
<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}}"
|
data-url="{{PhotoURL .Filename}}" data-photo-id="{{.ID}}"
|
||||||
{{if .AltText}}title="{{.AltText}}"{{end}}
|
{{if .AltText}}title="{{.AltText}}"{{end}}
|
||||||
{{if BlurExplicit .}}class="blurred-explicit"
|
{{if and (not (BlurExplicit .)) (not (eq ($Root.CurrentUser.GetProfileField "autoplay_gif") "false"))}}autoplay{{end}}
|
||||||
{{else if (not (eq ($Root.CurrentUser.GetProfileField "autoplay_gif") "false"))}}autoplay
|
>
|
||||||
{{end}}>
|
|
||||||
<source src="{{PhotoURL .Filename}}" type="video/mp4">
|
<source src="{{PhotoURL .Filename}}" type="video/mp4">
|
||||||
</video>
|
</video>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user