diff --git a/4chan_x.user.js b/4chan_x.user.js
index 2c42e44ea..aec93ad1d 100644
--- a/4chan_x.user.js
+++ b/4chan_x.user.js
@@ -1282,14 +1282,43 @@
if (g.dead) {
value = 404;
disabled = true;
- } else if (data.progress) {
- value = data.progress;
+ } else {
+ value = qr.cooldown.seconds || data.progress || value;
}
if (!qr.el) return;
input = qr.status.input;
input.value = value || 'Submit';
return input.disabled = disabled || false;
},
+ cooldown: {
+ init: function() {
+ if (!conf['Cooldown']) return;
+ qr.cooldown.start($.get("/" + g.BOARD + "/cooldown", 0));
+ return $.on(window, 'storage', function(e) {
+ var timeout;
+ if (e.key === ("" + NAMESPACE + "/" + g.BOARD + "/cooldown") && (timeout = JSON.parse(e.newValue))) {
+ return qr.cooldown.start(timeout);
+ }
+ });
+ },
+ start: function(timeout) {
+ var seconds;
+ seconds = Math.floor((timeout - Date.now()) / 1000);
+ return qr.cooldown.count(seconds);
+ },
+ set: function(seconds) {
+ if (!conf['Cooldown']) return;
+ qr.cooldown.count(seconds);
+ return $.set("/" + g.BOARD + "/cooldown", Date.now() + seconds * SECOND);
+ },
+ count: function(seconds) {
+ if (!((60 >= seconds && seconds >= 0))) return;
+ setTimeout(qr.cooldown.count, 1000, seconds - 1);
+ if (seconds === 0) $["delete"]("/" + g.BOARD + "/cooldown");
+ qr.cooldown.seconds = seconds;
+ return qr.status();
+ }
+ },
pickThread: function(thread) {
return $('select', qr.el).value = thread;
},
@@ -1540,7 +1569,7 @@
});
qr.mimeTypes = mimeTypes.split(', ');
qr.spoiler = !!$('#com_submit + label');
- qr.el = ui.dialog('qr', 'top:0;right:0;', "
");
+ qr.el = ui.dialog('qr', 'top:0;right:0;', "");
if (!g.REPLY) {
$.on($('select', qr.el), 'mousedown', function(e) {
return e.stopPropagation();
@@ -1585,6 +1614,7 @@
});
qr.status.input = $('[type=submit]', qr.el);
qr.status();
+ qr.cooldown.init();
qr.captcha.init();
qr.message.init();
return $.add(d.body, qr.el);
@@ -1592,6 +1622,7 @@
submit: function(e) {
var captcha, captchas, challenge, err, file, m, post, reader, reply, response, threadID;
if (e != null) e.preventDefault();
+ if (qr.cooldown.seconds) return;
qr.message.send({
abort: true
});
@@ -1653,7 +1684,7 @@
return qr.message.send(post);
},
response: function(html) {
- var b, err, node, persona, reply, sage;
+ var b, err, node, persona, postNumber, reply, thread, _, _ref;
qr.status();
if (!(b = $('td b', $.el('a', {
innerHTML: html
@@ -1662,14 +1693,19 @@
} else if (b.childElementCount) {
if (b.firstChild.tagName) node = b.firstChild;
err = b.firstChild.textContent;
- if (err === 'You seem to have mistyped the verification.') {}
+ if (err === 'You seem to have mistyped the verification.') {
+ qr.cooldown.set(10);
+ }
}
if (err) {
qr.error(err, node);
return;
}
reply = qr.replies[0];
- sage = /sage/i.test(reply.email);
+ _ref = b.lastChild.textContent.match(/thread:(\d+),no:(\d+)/), _ = _ref[0], thread = _ref[1], postNumber = _ref[2];
+ if (thread === 0) {} else {
+ qr.cooldown.set(/sage/i.test(reply.email) ? 60 : 30);
+ }
persona = $.get('qr.persona', {});
persona = {
name: reply.name,
@@ -3586,11 +3622,11 @@ textarea.field {\
width: 100%;\
}\
#qr [type=file] {\
- width: 80%;\
+ width: 75%;\
}\
#qr [type=submit] {\
padding: 0 -moz-calc(1px); /* Gecko does not respect box-sizing: border-box */\
- width: 20%;\
+ width: 25%;\
}\
\
.new {\
diff --git a/script.coffee b/script.coffee
index 9d84694ab..1377fed15 100644
--- a/script.coffee
+++ b/script.coffee
@@ -923,13 +923,37 @@ qr =
if g.dead
value = 404
disabled = true
- else if data.progress
- value = data.progress
+ else
+ # do not cancel `value = 'Loading'` once the cooldown is over
+ value = qr.cooldown.seconds or data.progress or value
return unless qr.el
{input} = qr.status
- input.value = value or 'Submit'
+ input.value = value or 'Submit' # dispaly "Auto #{...}" when auto postan
input.disabled = disabled or false
+ cooldown:
+ init: ->
+ return unless conf['Cooldown']
+ qr.cooldown.start $.get "/#{g.BOARD}/cooldown", 0
+ $.on window, 'storage', (e) ->
+ if e.key is "#{NAMESPACE}/#{g.BOARD}/cooldown" and timeout = JSON.parse e.newValue
+ qr.cooldown.start timeout
+ start: (timeout) ->
+ seconds = Math.floor (timeout - Date.now()) / 1000
+ qr.cooldown.count seconds
+ set: (seconds) ->
+ return unless conf['Cooldown']
+ qr.cooldown.count seconds
+ $.set "/#{g.BOARD}/cooldown", Date.now() + seconds*SECOND
+ count: (seconds) ->
+ return unless 60 >= seconds >= 0
+ setTimeout qr.cooldown.count, 1000, seconds-1
+ if seconds is 0
+ $.delete "/#{g.BOARD}/cooldown"
+ # auto postan
+ qr.cooldown.seconds = seconds
+ qr.status()
+
pickThread: (thread) ->
$('select', qr.el).value = thread
@@ -1133,7 +1157,7 @@ qr =
-
+
"
unless g.REPLY
@@ -1160,12 +1184,16 @@ qr =
qr.status.input = $ '[type=submit]', qr.el
qr.status()
+ qr.cooldown.init()
qr.captcha.init()
qr.message.init()
$.add d.body, qr.el
submit: (e) ->
e?.preventDefault()
+ if qr.cooldown.seconds
+ # toggle auto postan
+ return
qr.message.send abort: true
reply = qr.replies[0]
@@ -1239,15 +1267,20 @@ qr =
node = b.firstChild if b.firstChild.tagName # duplicate image link
err = b.firstChild.textContent
if err is 'You seem to have mistyped the verification.'
- ;# cooldown to prevent autoban
+ qr.cooldown.set 10 # prevent autoban
+ # turn auto postan ON? Might depend if we have captchas in stock or not
if err
qr.error err, node
return
reply = qr.replies[0]
- sage = /sage/i.test reply.email
- # cooldown
+
+ [_, thread, postNumber] = b.lastChild.textContent.match /thread:(\d+),no:(\d+)/
+ if thread is 0 # new thread
+ # auto noko to postNumber
+ else
+ qr.cooldown.set if /sage/i.test reply.email then 60 else 30
persona = $.get 'qr.persona', {}
persona =
@@ -2825,11 +2858,11 @@ textarea.field {
width: 100%;
}
#qr [type=file] {
- width: 80%;
+ width: 75%;
}
#qr [type=submit] {
padding: 0 -moz-calc(1px); /* Gecko does not respect box-sizing: border-box */
- width: 20%;
+ width: 25%;
}
.new {