Thread creation cooldown. Fix cooldown between different post-type. Fix /q/ cooldowns?

Ugh. see #774
This commit is contained in:
Nicolas Stepien 2012-10-01 17:33:05 +02:00
parent f411eb3e99
commit 027836b78f
3 changed files with 225 additions and 83 deletions

View File

@ -1738,7 +1738,7 @@
$.on(link.firstChild, 'click', function() {
QR.open();
if (!g.REPLY) {
$('select', QR.el).value = 'new';
QR.threadSelector.value = 'new';
}
return $('textarea', QR.el).focus();
});
@ -1836,44 +1836,118 @@
},
cooldown: {
init: function() {
var length, timeout, _ref;
if (!Conf['Cooldown']) {
return;
}
_ref = $.get("/" + g.BOARD + "/cooldown", {}), timeout = _ref.timeout, length = _ref.length;
if (timeout) {
QR.cooldown.start(timeout, length);
QR.cooldown.types = {
thread: (function() {
switch (g.BOARD) {
case 'q':
return 86400;
case 'b':
case 'soc':
case 'r9k':
return 600;
default:
return 300;
}
})(),
sage: g.BOARD === 'q' ? 600 : 60,
file: g.BOARD === 'q' ? 300 : 30,
post: g.BOARD === 'q' ? 60 : 30
};
QR.cooldown.cooldowns = $.get("" + g.BOARD + ".cooldown", {});
QR.cooldown.start();
return $.sync("" + g.BOARD + ".cooldown", QR.cooldown.sync);
},
start: function() {
if (QR.cooldown.isCounting) {
return;
}
return $.sync("/" + g.BOARD + "/cooldown", QR.cooldown.start);
QR.cooldown.isCounting = true;
return QR.cooldown.count();
},
start: function(timeout, length) {
var seconds;
seconds = Math.floor((timeout - Date.now()) / 1000);
return QR.cooldown.count(seconds, length);
sync: function(cooldowns) {
QR.cooldown.cooldowns = cooldowns;
return QR.cooldown.start();
},
set: function(seconds) {
set: function(data) {
var cooldown, hasFile, isReply, isSage, start, type;
if (!Conf['Cooldown']) {
return;
}
QR.cooldown.count(seconds, seconds);
return $.set("/" + g.BOARD + "/cooldown", {
timeout: Date.now() + seconds * $.SECOND,
length: seconds
});
start = Date.now();
if (data.delay) {
cooldown = {
delay: data.delay
};
} else {
isSage = /sage/i.test(data.post.email);
hasFile = !!data.post.file;
isReply = data.isReply;
type = !isReply ? 'thread' : isSage ? 'sage' : hasFile ? 'file' : 'post';
cooldown = {
isReply: isReply,
isSage: isSage,
hasFile: hasFile,
timeout: start + QR.cooldown.types[type] * $.SECOND
};
}
QR.cooldown.cooldowns[start] = cooldown;
$.set("" + g.BOARD + ".cooldown", QR.cooldown.cooldowns);
return QR.cooldown.start();
},
count: function(seconds, length) {
if (!((0 <= seconds && seconds <= length))) {
unset: function(id) {
delete QR.cooldown.cooldowns[id];
return $.set("" + g.BOARD + ".cooldown", QR.cooldown.cooldowns);
},
count: function() {
var cooldown, cooldowns, elapsed, hasFile, isReply, isSage, now, post, seconds, start, type, types, _ref;
if (Object.keys(QR.cooldown.cooldowns).length) {
setTimeout(QR.cooldown.count, 1000);
} else {
$["delete"]("" + g.BOARD + ".cooldown");
QR.cooldown.isCounting = false;
return;
}
setTimeout(QR.cooldown.count, 1000, seconds - 1, length);
QR.cooldown.seconds = seconds;
if (seconds === 0) {
$["delete"]("/" + g.BOARD + "/cooldown");
if (QR.cooldown.auto) {
QR.submit();
if ((isReply = g.REPLY ? true : QR.threadSelector.value !== 'new')) {
post = QR.replies[0];
isSage = /sage/i.test(post.email);
hasFile = !!post.file;
}
now = Date.now();
seconds = null;
_ref = QR.cooldown, types = _ref.types, cooldowns = _ref.cooldowns;
for (start in cooldowns) {
cooldown = cooldowns[start];
if ('delay' in cooldown) {
if (cooldown.delay) {
seconds = Math.max(seconds, cooldown.delay--);
} else {
seconds = Math.max(seconds, 0);
QR.cooldown.unset(start);
}
continue;
}
type = isReply && cooldown.isReply ? isSage && cooldown.isSage ? 'sage' : hasFile && cooldown.hasFile ? 'file' : 'post' : !(isReply || cooldown.isReply) ? type = 'thread' : void 0;
if (type) {
elapsed = Math.floor((now - start) / 1000);
if (elapsed >= 0) {
seconds = Math.max(seconds, types[type] - elapsed);
}
type = '';
}
if (!((start <= now && now <= cooldown.timeout))) {
QR.cooldown.unset(start);
}
}
return QR.status();
QR.cooldown.seconds = seconds;
if (seconds !== null) {
QR.status();
}
if (seconds === 0 && QR.cooldown.auto) {
return QR.submit();
}
}
},
quote: function(e) {
@ -1883,7 +1957,7 @@
}
QR.open();
if (!g.REPLY) {
$('select', QR.el).value = $.x('ancestor::div[parent::div[@class="board"]]', this).id.slice(1);
QR.threadSelector.value = $.x('ancestor::div[parent::div[@class="board"]]', this).id.slice(1);
}
id = this.previousSibling.hash.slice(2);
text = ">>" + id + "\n";
@ -2173,10 +2247,7 @@
(QR.replies[index - 1] || QR.replies[index + 1]).select();
}
QR.replies.splice(index, 1);
if (typeof (_base1 = window.URL || window.webkitURL).revokeObjectURL === "function") {
_base1.revokeObjectURL(this.url);
}
return delete this;
return typeof (_base1 = window.URL || window.webkitURL).revokeObjectURL === "function" ? _base1.revokeObjectURL(this.url) : void 0;
};
return _Class;
@ -2342,11 +2413,12 @@
id = thread.id.slice(1);
threads += "<option value=" + id + ">Thread " + id + "</option>";
}
$.prepend($('.move > span', QR.el), $.el('select', {
QR.threadSelector = $.el('select', {
innerHTML: threads,
title: 'Create a new thread / Reply to a thread'
}));
$.on($('select', QR.el), 'mousedown', function(e) {
});
$.prepend($('.move > span', QR.el), QR.threadSelector);
$.on(QR.threadSelector, 'mousedown', function(e) {
return e.stopPropagation();
});
}
@ -2380,7 +2452,7 @@
$.on($("[name=" + name + "]", QR.el), 'input', function() {
var _ref2;
QR.selected[this.name] = this.value;
if (QR.cooldown.auto && QR.selected === QR.replies[0] && (0 < (_ref2 = QR.cooldown.seconds) && _ref2 < 6)) {
if (QR.cooldown.auto && QR.selected === QR.replies[0] && (0 < (_ref2 = QR.cooldown.seconds) && _ref2 <= 5)) {
return QR.cooldown.auto = false;
}
});
@ -2406,7 +2478,7 @@
}
QR.abort();
reply = QR.replies[0];
threadID = g.THREAD_ID || $('select', QR.el).value;
threadID = g.THREAD_ID || QR.threadSelector.value;
if (threadID === 'new') {
if (((_ref = g.BOARD) === 'vg' || _ref === 'q') && !reply.sub) {
err = 'New threads require a subject.';
@ -2506,7 +2578,7 @@
return QR.ajax = $.ajax($.id('postForm').parentNode.action, callbacks, opts);
},
response: function(html) {
var bs, doc, err, msg, persona, postID, reply, sage, seconds, threadID, _, _ref, _ref1;
var bs, doc, err, msg, persona, postID, reply, threadID, _, _ref, _ref1;
doc = d.implementation.createHTMLDocument('');
doc.documentElement.innerHTML = html;
if (doc.title === '4chan - Banned') {
@ -2527,7 +2599,9 @@
err.textContent = 'Error: You seem to have mistyped the CAPTCHA.';
}
QR.cooldown.auto = QR.captchaIsEnabled ? !!$.get('captchas', []).length : true;
QR.cooldown.set(2);
QR.cooldown.set({
delay: 2
});
} else {
QR.cooldown.auto = false;
}
@ -2551,13 +2625,14 @@
postID: postID
}
}));
QR.cooldown.set({
post: reply,
isReply: threadID !== '0'
});
if (threadID === '0') {
location.pathname = "/" + g.BOARD + "/res/" + postID;
} else {
QR.cooldown.auto = QR.replies.length > 1;
sage = /sage/i.test(reply.email);
seconds = g.BOARD === 'q' ? sage ? 600 : reply.file ? 300 : 60 : sage ? 60 : 30;
QR.cooldown.set(seconds);
if (Conf['Open Reply in New Tab'] && !g.REPLY && !QR.cooldown.auto) {
$.open("//boards.4chan.org/" + g.BOARD + "/res/" + threadID + "#p" + postID);
}

View File

@ -1,4 +1,8 @@
master
- Mayhem
Added thread creation QR cooldown.
Fix QR cooldown timer between non-sage and sage posts. You can submit a non-sage post 30 seconds after a sage one.
Fix /q/ QR cooldowns.
2.35.4
- Mayhem

View File

@ -1342,7 +1342,7 @@ QR =
link = $.el 'h1', innerHTML: "<a href=javascript:;>#{if g.REPLY then 'Reply to Thread' else 'Start a Thread'}</a>"
$.on link.firstChild, 'click', ->
QR.open()
$('select', QR.el).value = 'new' unless g.REPLY
QR.threadSelector.value = 'new' unless g.REPLY
$('textarea', QR.el).focus()
$.before $.id('postForm'), link
@ -1418,32 +1418,108 @@ QR =
cooldown:
init: ->
return unless Conf['Cooldown']
{timeout, length} = $.get "/#{g.BOARD}/cooldown", {}
QR.cooldown.start timeout, length if timeout
$.sync "/#{g.BOARD}/cooldown", QR.cooldown.start
start: (timeout, length) ->
seconds = Math.floor (timeout - Date.now()) / 1000
QR.cooldown.count seconds, length
set: (seconds) ->
QR.cooldown.types =
thread: switch g.BOARD
when 'q' then 86400
when 'b', 'soc', 'r9k' then 600
else 300
sage: if g.BOARD is 'q' then 600 else 60
file: if g.BOARD is 'q' then 300 else 30
post: if g.BOARD is 'q' then 60 else 30
QR.cooldown.cooldowns = $.get "#{g.BOARD}.cooldown", {}
QR.cooldown.start()
$.sync "#{g.BOARD}.cooldown", QR.cooldown.sync
start: ->
return if QR.cooldown.isCounting
QR.cooldown.isCounting = true
QR.cooldown.count()
sync: (cooldowns) ->
QR.cooldown.cooldowns = cooldowns
QR.cooldown.start()
set: (data) ->
return unless Conf['Cooldown']
QR.cooldown.count seconds, seconds
$.set "/#{g.BOARD}/cooldown",
timeout: Date.now() + seconds * $.SECOND
length: seconds
count: (seconds, length) ->
return unless 0 <= seconds <= length
setTimeout QR.cooldown.count, 1000, seconds-1, length
start = Date.now()
if data.delay
cooldown = delay: data.delay
else
isSage = /sage/i.test data.post.email
hasFile = !!data.post.file
isReply = data.isReply
type =
unless isReply
'thread'
else
if isSage
'sage'
else if hasFile
'file'
else
'post'
cooldown =
isReply: isReply
isSage: isSage
hasFile: hasFile
timeout: start + QR.cooldown.types[type] * $.SECOND
QR.cooldown.cooldowns[start] = cooldown
$.set "#{g.BOARD}.cooldown", QR.cooldown.cooldowns
QR.cooldown.start()
unset: (id) ->
delete QR.cooldown.cooldowns[id]
$.set "#{g.BOARD}.cooldown", QR.cooldown.cooldowns
count: ->
if Object.keys(QR.cooldown.cooldowns).length
setTimeout QR.cooldown.count, 1000
else
$.delete "#{g.BOARD}.cooldown"
QR.cooldown.isCounting = false
return
if (isReply = if g.REPLY then true else QR.threadSelector.value isnt 'new')
post = QR.replies[0]
isSage = /sage/i.test post.email
hasFile = !!post.file
now = Date.now()
seconds = null
{types, cooldowns} = QR.cooldown
for start, cooldown of cooldowns
if 'delay' of cooldown
if cooldown.delay
seconds = Math.max seconds, cooldown.delay--
else
seconds = Math.max seconds, 0
QR.cooldown.unset start
continue
# Only cooldowns relevant to this post can set the seconds value.
# Unset outdated cooldowns that can no longer impact us.
type =
if isReply and cooldown.isReply
if isSage and cooldown.isSage
'sage'
else if hasFile and cooldown.hasFile
'file'
else
'post'
else unless isReply or cooldown.isReply
type = 'thread'
if type
elapsed = Math.floor (now - start) / 1000
if elapsed >= 0 # clock changed since then?
seconds = Math.max seconds, types[type] - elapsed
type = ''
unless start <= now <= cooldown.timeout
QR.cooldown.unset start
QR.cooldown.seconds = seconds
if seconds is 0
$.delete "/#{g.BOARD}/cooldown"
QR.submit() if QR.cooldown.auto
QR.status()
QR.status() if seconds isnt null
QR.submit() if seconds is 0 and QR.cooldown.auto
quote: (e) ->
e?.preventDefault()
QR.open()
unless g.REPLY
$('select', QR.el).value = $.x('ancestor::div[parent::div[@class="board"]]', @).id[1..]
QR.threadSelector.value = $.x('ancestor::div[parent::div[@class="board"]]', @).id[1..]
# Make sure we get the correct number, even with XXX censors
id = @previousSibling.hash[2..]
text = ">>#{id}\n"
@ -1674,7 +1750,6 @@ QR =
(QR.replies[index-1] or QR.replies[index+1]).select()
QR.replies.splice index, 1
(window.URL or window.webkitURL).revokeObjectURL? @url
delete @
captcha:
init: ->
@ -1804,10 +1879,11 @@ QR =
for thread in $$ '.thread'
id = thread.id[1..]
threads += "<option value=#{id}>Thread #{id}</option>"
$.prepend $('.move > span', QR.el), $.el 'select'
QR.threadSelector = $.el 'select'
innerHTML: threads
title: 'Create a new thread / Reply to a thread'
$.on $('select', QR.el), 'mousedown', (e) -> e.stopPropagation()
$.prepend $('.move > span', QR.el), QR.threadSelector
$.on QR.threadSelector, 'mousedown', (e) -> e.stopPropagation()
$.on $('#autohide', QR.el), 'change', QR.toggleHide
$.on $('.close', QR.el), 'click', QR.close
$.on $('#dump', QR.el), 'click', -> QR.el.classList.toggle 'dump'
@ -1828,7 +1904,7 @@ QR =
QR.selected[@name] = @value
# Disable auto-posting if you're typing in the first reply
# during the last 5 seconds of the cooldown.
if QR.cooldown.auto and QR.selected is QR.replies[0] and 0 < QR.cooldown.seconds < 6
if QR.cooldown.auto and QR.selected is QR.replies[0] and 0 < QR.cooldown.seconds <= 5
QR.cooldown.auto = false
QR.status.input = $ 'input[type=submit]', QR.el
@ -1851,7 +1927,7 @@ QR =
QR.abort()
reply = QR.replies[0]
threadID = g.THREAD_ID or $('select', QR.el).value
threadID = g.THREAD_ID or QR.threadSelector.value
# prevent errors
if threadID is 'new'
@ -1972,7 +2048,7 @@ QR =
true
# Too many frequent mistyped captchas will auto-ban you!
# On connection error, the post most likely didn't go through.
QR.cooldown.set 2
QR.cooldown.set delay: 2
else # stop auto-posting
QR.cooldown.auto = false
QR.status()
@ -1997,29 +2073,16 @@ QR =
threadID: threadID
postID: postID
QR.cooldown.set
post: reply
isReply: threadID isnt '0'
if threadID is '0' # new thread
# auto-noko
location.pathname = "/#{g.BOARD}/res/#{postID}"
else
# Enable auto-posting if we have stuff to post, disable it otherwise.
QR.cooldown.auto = QR.replies.length > 1
sage = /sage/i.test reply.email
seconds =
# 300 seconds cooldown for new threads
# q: 86400 seconds
# b soc r9k: 600 seconds
if g.BOARD is 'q'
if sage
600
else if reply.file
300
else
60
else if sage
60
else
30
QR.cooldown.set seconds
if Conf['Open Reply in New Tab'] and !g.REPLY and !QR.cooldown.auto
$.open "//boards.4chan.org/#{g.BOARD}/res/#{threadID}#p#{postID}"