Skip to content

Commit 58fbd25

Browse files
authored
Add pre-send check and warning (attempt 2) (#300)
* Add pre-send check and warning * Use RegEx UNTESTED * Add more and improve RegEx patterns * Add more and improve RegEx patterns 2 * Revamp code, add link on punishment description * Improve RegEx patterns * Disable JS-side sanitization It is sanitized on Hugo already
1 parent 2c8cc34 commit 58fbd25

3 files changed

Lines changed: 113 additions & 17 deletions

File tree

i18n/en.yaml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,17 @@ FeedbackPage:
161161
ContentPlaceholder: Please provide as much detail as you can.
162162
SendEnabled: Send list of my currently enabled addons (recommended)
163163
SubmitButton: Send
164-
164+
PreSendWarning:
165+
Warning: "Warning:"
166+
Override: If you are really sure to send this feedback, you can press the "Send" button again.
167+
Variations:
168+
NotST:
169+
Heading: We are not the Scratch Team.
170+
Description: Keep in mind that Scratch Addons is not affiliated with the Scratch website or the organizations that maintain it. You are still welcome to give ideas to improve your experience on Scratch with Scratch Addons.
171+
Punishment:
172+
Heading: We can't punish people. We are not the Scratch Team. <br>
173+
Description: "Scratch Addons is not affiliated with the Scratch website or the organizations that maintain it. We have no control of the content and the moderation on the Scratch website. {{ .Tag1Start }}There are many ways that you can report on the Scratch website.{{ .Tag1End }}"
174+
165175
# Strings used for /scratch-messaging-transition
166176
SMTPage:
167177
ScratchMessagingLogoAlt: Scratch Messaging Extension logo

layouts/shortcodes/specifics/feedback-form.html

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,29 @@
1+
{{ $ts := now.UnixMilli }}
2+
13
<script>
24
window.i18nStrings = {
35
statusSending: '{{ T "FeedbackPage.Status.Sending" }}',
46
statusSuccess: '{{ T "FeedbackPage.Status.Success" }}',
57
statusFailed: '{{ T "FeedbackPage.Status.Failed" }}',
68
statusOffline: '{{ T "FeedbackPage.Status.Offline" }}',
79
noAddonsList: '{{ T "FeedbackPage.NoAddonsList" }}',
8-
submitButton: '{{ T "FeedbackPage.SubmitButton" }}',
10+
preSendWarning: {
11+
warning: '{{ T "FeedbackPage.PreSendWarning.Warning" }}',
12+
override: '{{ T "FeedbackPage.PreSendWarning.Override" }}',
13+
variations: {
14+
notST: {
15+
heading: '{{ T "FeedbackPage.PreSendWarning.Variations.NotST.Heading" }}',
16+
description: '{{ T "FeedbackPage.PreSendWarning.Variations.NotST.Description" | htmlEscape }}',
17+
},
18+
punishment: {
19+
heading: '{{ T "FeedbackPage.PreSendWarning.Variations.Punishment.Heading" }}',
20+
description: '{{ T "FeedbackPage.PreSendWarning.Variations.Punishment.Description" ( dict "Tag1Start" (add $ts 1) "Tag1End" (add $ts 2) ) | htmlEscape }}',
21+
}
22+
}
23+
},
24+
submitButton: '{{ T "FeedbackPage.SubmitButton" }}'
925
}
26+
window.i18nTimestamp = Number('{{ $ts }}')
1027
</script>
1128
<script defer src="/assets/js/feedback.js"></script>
1229

static/assets/js/feedback.js

Lines changed: 84 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
const variations = {
2+
notST: [
3+
/\bscratch\s*team\b/i,
4+
/\bst\b/,
5+
],
6+
punishment: [
7+
/\bban(ing|ned)?\b/,
8+
/\bunban(ing|ned)?\b/,
9+
/\bkick(ing|ed)?\b/,
10+
/\bpunish(ing|ed|ment)?\b/,
11+
/\b(please|pl[sz])\s*block(ing|ed)?\b/,
12+
/\b(please|pl[sz])\s*mut(ed?|ing)\b/,
13+
/\b(please|pl[sz])\s*unmut(ed?|ing)\b/,
14+
/\bblock(ing|ed)?\s*(please|pl[sz])\b/,
15+
/\bmut(ed?|ing)\s*(please|pl[sz])\b/,
16+
/\bunmut(ed?|ing)\s*(please|pl[sz])\b/,
17+
]
18+
}
19+
120
const i18n = window.i18nStrings
221
let lastFeedbackRequestTime = localStorage.getItem("lastFeedbackRequestTime")
322
let wakeUpTimeout = setTimeout(() => {}, 0)
@@ -7,6 +26,8 @@ const usernameField = form.querySelector('#feedback-username')
726
const contentField = form.querySelector("#feedback-content")
827
const submitButton = form.querySelector("#feedback-submit")
928
const addonsListCheckbox = form.querySelector("#feedback-addons-list")
29+
const statusEl = document.querySelector('#feedback-status')
30+
let hasWarnedContent = false
1031

1132
const version = new URL(location.href).searchParams.get("ext_version") || new URL(location.href).searchParams.get("version")
1233

@@ -21,7 +42,6 @@ if (location.hash.length && /[0-9A-Fa-f]/g.test(location.hash.substring(2))) {
2142
}
2243

2344
const setStatus = (statusText, status) => {
24-
const statusEl = document.querySelector('#feedback-status')
2545
statusEl.textContent = statusText
2646
statusEl.hidden = false
2747
statusEl.classList.remove([...statusEl.classList].filter(className => /alert-/.exec(className))[0])
@@ -80,13 +100,61 @@ const holdSendButton = seconds => {
80100
step()
81101
}
82102

103+
const setPreSendWarning = (heading, description) => {
104+
setStatus("", "warning")
105+
const headingEl = document.createElement('p')
106+
headingEl.textContent = heading
107+
statusEl.appendChild(headingEl)
108+
headingEl.insertAdjacentHTML('afterbegin', `<b>${i18n.preSendWarning.warning}</b> `)
109+
const descriptionEl = document.createElement('p')
110+
descriptionEl.innerHTML = description
111+
statusEl.appendChild(descriptionEl)
112+
const overrideEl = document.createElement('p')
113+
overrideEl.textContent = i18n.preSendWarning.override
114+
overrideEl.classList.add('mb-0')
115+
statusEl.appendChild(overrideEl)
116+
holdSendButton(5)
117+
}
118+
119+
for (const variation in variations) {
120+
const variationObj = i18n.preSendWarning.variations[variation]
121+
// for (const key in variationObj) {
122+
// variationObj[key] = DOMPurify.sanitize(variationObj[key])
123+
// }
124+
}
125+
const punishment = i18n.preSendWarning.variations.punishment
126+
punishment.description = punishment.description.replace(window.i18nTimestamp + 1, '<a href="https://en.scratch-wiki.info/wiki/Report">').replace(window.i18nTimestamp + 2, '</a>')
127+
128+
const preSendCheck = content => {
129+
content = content.toLowerCase()
130+
let warningText = false
131+
for (var variation in variations) {
132+
if (variations[variation].some(el => content.search(el) + 1)) {
133+
warningText = [i18n.preSendWarning.variations[variation].heading, i18n.preSendWarning.variations[variation].description]
134+
break
135+
}
136+
}
137+
if (warningText) {
138+
if (hasWarnedContent && hasWarnedContent === content) {
139+
hasWarnedContent = ""
140+
return true
141+
} else {
142+
hasWarnedContent = content
143+
setPreSendWarning(...warningText)
144+
return false
145+
}
146+
} else {
147+
return true
148+
}
149+
}
150+
// preSendCheck('I hate this guy please ban him')
151+
83152
form.addEventListener("submit", async event => {
84153
event.preventDefault()
85154
setStatus(i18n.statusSending, "primary")
86155

87156
usernameField.readOnly = true
88157
contentField.readOnly = true
89-
submitButton.disabled = true
90158

91159
// document.querySelector("#sending").style.display = "block";
92160

@@ -99,19 +167,20 @@ form.addEventListener("submit", async event => {
99167
enabledAddons: addonsListCheckbox.checked ? enabledAddons : null
100168
}
101169

102-
try {
103-
lastFeedbackRequestTime = Date.now()
104-
localStorage.setItem("lastFeedbackRequestTime", lastFeedbackRequestTime)
105-
const res = await fetch("https://scratchaddons-feedback.glitch.me/send", {
106-
method: "POST",
107-
body: JSON.stringify(body)
108-
})
109-
if (!res.ok) throw "";
110-
holdSendButton(10)
111-
setStatus(i18n.statusSuccess, "success")
112-
} catch(err) {
113-
setStatus(i18n.statusFailed, "danger")
114-
submitButton.disabled = false
170+
if (preSendCheck(contentField.value)) {
171+
try {
172+
lastFeedbackRequestTime = Date.now()
173+
localStorage.setItem("lastFeedbackRequestTime", lastFeedbackRequestTime)
174+
const res = await fetch("https://scratchaddons-feedback.glitch.me/send", {
175+
method: "POST",
176+
body: JSON.stringify(body)
177+
})
178+
if (!res.ok) throw "";
179+
holdSendButton(10)
180+
setStatus(i18n.statusSuccess, "success")
181+
} catch(err) {
182+
setStatus(i18n.statusFailed, "danger")
183+
}
115184
}
116185

117186
usernameField.readOnly = false

0 commit comments

Comments
 (0)