diff --git a/4chan_x.user.js b/4chan_x.user.js
index bf0e0ddeb..42d0af6e0 100644
--- a/4chan_x.user.js
+++ b/4chan_x.user.js
@@ -59,7 +59,7 @@
*/
(function() {
- var $, $$, Favicon, NAMESPACE, Recaptcha, Time, anonymize, conf, config, cooldown, d, expandComment, expandThread, firstRun, g, imgExpand, imgGif, imgHover, imgPreloading, key, keybinds, log, main, nav, nodeInserted, options, qr, quoteBacklink, quoteInline, quoteOP, quotePreview, redirect, replyHiding, reportButton, revealSpoilers, sauce, threadHiding, threadStats, threading, titlePost, ui, unread, updater, val, watcher, _ref;
+ var $, $$, DAY, Favicon, HOUR, MINUTE, NAMESPACE, Recaptcha, SECOND, Time, anonymize, conf, config, cooldown, d, expandComment, expandThread, firstRun, g, imgExpand, imgGif, imgHover, imgPreloading, key, keybinds, log, main, nav, nodeInserted, options, qr, quoteBacklink, quoteInline, quoteOP, quotePreview, redirect, replyHiding, reportButton, revealSpoilers, sauce, threadHiding, threadStats, threading, titlePost, ui, unread, updater, val, watcher, _ref;
var __slice = Array.prototype.slice;
config = {
main: {
@@ -183,6 +183,10 @@
};
}
NAMESPACE = 'AEOS.4chan_x.';
+ SECOND = 1000;
+ MINUTE = 60 * SECOND;
+ HOUR = 60 * MINUTE;
+ DAY = 24 * HOUR;
d = document;
g = {
callbacks: []
@@ -1215,7 +1219,7 @@
g.callbacks.push(qr.node);
$.bind(window, 'message', qr.message);
$.bind($('#recaptcha_challenge_field_holder'), 'DOMNodeInserted', qr.captchaNode);
- qr.captcha = [];
+ qr.captchaTime = Date.now();
iframe = $.el('iframe', {
name: 'iframe',
hidden: true
@@ -1243,14 +1247,27 @@
return $.replace(oldFile, file);
},
autoPost: function() {
- var captcha, responseField;
- if (!(captcha = qr.captcha.shift())) {
+ /*
+ captchas expire after 5 hours (couldn't find an official source, so
+ anonymous empirically verified). cutoff 5 minutes before then, b/c posting
+ takes time.
+ */
+ var captcha, captchas, cutoff, responseField;
+ cutoff = Date.now() - 5 * HOUR + 5 * MINUTE;
+ captchas = $.getValue('captchas', []);
+ while (captcha = captchas.shift()) {
+ if (captcha.time > cutoff) {
+ break;
+ }
+ }
+ $.setValue('captchas', captchas);
+ responseField = $('#recaptcha_response_field', qr.el);
+ responseField.nextSibling.textContent = captchas.length + ' captchas';
+ if (!captcha) {
return;
}
$('#recaptcha_challenge_field', qr.el).value = captcha.challenge;
- responseField = $('#recaptcha_response_field', qr.el);
responseField.value = captcha.response;
- responseField.nextSibling.textContent = qr.captcha.length + ' captcha cached';
return qr.submit.call($('form', qr.el));
},
captchaNode: function(e) {
@@ -1260,10 +1277,11 @@
}
target = e.target;
$('img', qr.el).src = "http://www.google.com/recaptcha/api/image?c=" + target.value;
- return $('#recaptcha_challenge_field', qr.el).value = target.value;
+ $('#recaptcha_challenge_field', qr.el).value = target.value;
+ return qr.captchaTime = Date.now();
},
captchaKeydown: function(e) {
- var blank;
+ var blank, captcha, l;
if (!(e.keyCode === 13 && this.value)) {
return;
}
@@ -1275,13 +1293,11 @@
if (conf['Auto Hide QR']) {
$('#autohide', qr.el).checked = true;
}
- return qr.captchaPush.call(this);
- },
- captchaPush: function() {
- var l;
- l = qr.captcha.push({
+ captcha = $.getValue('captcha', []);
+ l = captcha.push({
challenge: $('#recaptcha_challenge_field', qr.el).value,
- response: this.value
+ response: this.value,
+ time: qr.captchaTime
});
this.nextSibling.textContent = l + ' captcha cached';
Recaptcha.reload();
@@ -1298,7 +1314,7 @@
THREAD_ID = g.THREAD_ID || $.x('ancestor::div[@class="thread"]/div', link).id;
spoiler = $('.postarea label') ? '' : '';
challenge = $('#recaptcha_challenge_field').value;
- html = " X
Quick Reply
";
+ html = " X Quick Reply
";
qr.el = ui.dialog('qr', {
top: '0px',
left: '0px'
@@ -2685,7 +2701,7 @@
};
main = {
init: function() {
- var DAY, callback, canPost, cutoff, form, hiddenThreads, id, lastChecked, now, op, pathname, table, temp, timestamp, tzOffset, _i, _j, _k, _l, _len, _len2, _len3, _len4, _ref2, _ref3, _ref4, _ref5, _ref6;
+ var callback, canPost, cutoff, form, hiddenThreads, id, lastChecked, now, op, pathname, table, temp, timestamp, tzOffset, _i, _j, _k, _l, _len, _len2, _len3, _len4, _ref2, _ref3, _ref4, _ref5, _ref6;
pathname = location.pathname.substring(1).split('/');
g.BOARD = pathname[0], temp = pathname[1];
if (temp === 'res') {
@@ -2715,7 +2731,6 @@
}
lastChecked = $.getValue('lastChecked', 0);
now = Date.now();
- DAY = 1000 * 60 * 60 * 24;
if (lastChecked < now - 1 * DAY) {
cutoff = now - 7 * DAY;
hiddenThreads = $.getValue("hiddenThreads/" + g.BOARD + "/", {});
diff --git a/script.coffee b/script.coffee
index 1edc6b2fa..aa5c57906 100644
--- a/script.coffee
+++ b/script.coffee
@@ -107,6 +107,10 @@ if not Object.keys
key for key in o
NAMESPACE = 'AEOS.4chan_x.'
+SECOND = 1000
+MINUTE = 60*SECOND
+HOUR = 60*MINUTE
+DAY = 24*HOUR
d = document
g = callbacks: []
@@ -959,7 +963,7 @@ qr =
g.callbacks.push qr.node
$.bind window, 'message', qr.message
$.bind $('#recaptcha_challenge_field_holder'), 'DOMNodeInserted', qr.captchaNode
- qr.captcha = []
+ qr.captchaTime = Date.now()
iframe = $.el 'iframe',
name: 'iframe'
@@ -983,11 +987,27 @@ qr =
$.replace oldFile, file
autoPost: ->
- return unless captcha = qr.captcha.shift()
- $('#recaptcha_challenge_field', qr.el).value = captcha.challenge
+ ###
+ captchas expire after 5 hours (couldn't find an official source, so
+ anonymous empirically verified). cutoff 5 minutes before then, b/c posting
+ takes time.
+ ###
+
+ cutoff = Date.now() - 5*HOUR + 5*MINUTE
+ captchas = $.getValue 'captchas', []
+
+ while captcha = captchas.shift()
+ if captcha.time > cutoff
+ break
+
+ $.setValue 'captchas', captchas
responseField = $ '#recaptcha_response_field', qr.el
+ responseField.nextSibling.textContent = captchas.length + ' captchas'
+
+ return unless captcha
+
+ $('#recaptcha_challenge_field', qr.el).value = captcha.challenge
responseField.value = captcha.response
- responseField.nextSibling.textContent = qr.captcha.length + ' captcha cached'
qr.submit.call $ 'form', qr.el
captchaNode: (e) ->
@@ -995,21 +1015,22 @@ qr =
{target} = e
$('img', qr.el).src = "http://www.google.com/recaptcha/api/image?c=" + target.value
$('#recaptcha_challenge_field', qr.el).value = target.value
+ qr.captchaTime = Date.now()
captchaKeydown: (e) ->
- return unless e.keyCode is 13 and @value #enter
+ return unless e.keyCode is 13 and @value #enter, captcha filled
blank = !$('textarea', qr.el).value and !$('input[type=file]', qr.el).files.length
return unless blank or cooldown.duration
$('#auto', qr.el).checked = true
$('#autohide', qr.el).checked = true if conf['Auto Hide QR']
- qr.captchaPush.call this
- captchaPush: ->
- l = qr.captcha.push
+ captcha = $.getValue 'captcha', []
+ l = captcha.push
challenge: $('#recaptcha_challenge_field', qr.el).value
response: @value
+ time: qr.captchaTime
@nextSibling.textContent = l + ' captcha cached'
Recaptcha.reload()
@value = ''
@@ -1039,7 +1060,7 @@ qr =
- #{qr.captcha.length} captcha cached
+ #{$.getValue('captcha', []).length} captcha cached
@@ -2117,7 +2138,6 @@ main =
lastChecked = $.getValue 'lastChecked', 0
now = Date.now()
- DAY = 1000 * 60 * 60 * 24
if lastChecked < now - 1*DAY
cutoff = now - 7*DAY
hiddenThreads = $.getValue "hiddenThreads/#{g.BOARD}/", {}