From f4b60634394e0f2363fb046ea88487fec7720641 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Sun, 24 Feb 2013 21:29:54 +0100 Subject: [PATCH] Clear timed-out cached captchas when the captcha is (re)loaded. That will avoid showing an incorrect count of cached captchas. Reorganize some captcha code. Also a tiny fix. --- 4chan_x.user.js | 99 ++++++++++++++++++++++++++++++------------------- src/qr.coffee | 72 ++++++++++++++++++----------------- 2 files changed, 99 insertions(+), 72 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index 1ff91b2ac..f72ba9b10 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -6250,7 +6250,7 @@ index = QR.replies.indexOf(this); if (QR.replies.length === 1) { new QR.reply().select(); - } else if (this.el.id === 'selected') { + } else if (this === QR.selected) { (QR.replies[index - 1] || QR.replies[index + 1]).select(); } QR.replies.splice(index, 1); @@ -6303,29 +6303,70 @@ } $.on(imgContainer, 'click', this.reload.bind(this)); $.on(this.nodes.input, 'keydown', this.keydown.bind(this)); - $.sync('captchas', this.count.bind(this)); - this.count($.get('captchas', [])); + $.sync('captchas', this.sync.bind(this)); + this.sync($.get('captchas', [])); this.reload(); $.addClass(QR.nodes.el, 'has-captcha'); return $.after(QR.nodes.com.parentNode, [imgContainer, inputContainer]); }, + sync: function(captchas) { + this.captchas = captchas; + return this.count(); + }, + getOne: function() { + var captcha, challenge, response; + this.clear(); + if (captcha = this.captchas.shift()) { + challenge = captcha.challenge, response = captcha.response; + this.count(); + $.set('captchas', this.captchas); + } else { + challenge = this.nodes.img.alt; + if (response = this.nodes.input.value) { + this.reload(); + } + } + if (response) { + response = response.trim(); + if (!/\s/.test(response)) { + response = "" + response + " " + response; + } + } + return { + challenge: challenge, + response: response + }; + }, save: function() { - var captcha, captchas, response; + var response; if (!(response = this.nodes.input.value.trim())) { return; } - captchas = $.get('captchas', []); - while ((captcha = captchas[0]) && captcha.time < Date.now()) { - captchas.shift(); - } - captchas.push({ + this.captchas.push({ challenge: this.nodes.challenge.firstChild.value, response: response, - time: this.timeout + timeout: this.timeout }); - $.set('captchas', captchas); - this.count(captchas); - return this.reload(); + this.count(); + this.reload(); + return $.set('captchas', this.captchas); + }, + clear: function() { + var captcha, i, now, _i, _len, _ref; + now = Date.now(); + _ref = this.captchas; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + captcha = _ref[i]; + if (captcha.timeout > now) { + break; + } + } + if (!i) { + return; + } + this.captchas = this.captchas.slice(i); + this.count(); + return $.set('captchas', this.captchas); }, load: function() { var challenge; @@ -6333,11 +6374,12 @@ challenge = this.nodes.challenge.firstChild.value; this.nodes.img.alt = challenge; this.nodes.img.src = "//www.google.com/recaptcha/api/image?c=" + challenge; - return this.nodes.input.value = null; + this.nodes.input.value = null; + return this.clear(); }, - count: function(arr) { + count: function() { var count; - count = arr.length; + count = this.captchas.length; this.nodes.input.placeholder = (function() { switch (count) { case 0: @@ -6466,7 +6508,7 @@ return $.event('QRDialogCreation', null, dialog); }, submit: function(e) { - var callbacks, captcha, captchas, challenge, err, filetag, m, opts, post, reply, response, textOnly, threadID, _ref; + var callbacks, challenge, err, filetag, m, opts, post, reply, response, textOnly, threadID, _ref, _ref1; if (e != null) { e.preventDefault(); } @@ -6508,28 +6550,9 @@ err = 'No file selected.'; } if (QR.captcha.isEnabled && !err) { - captchas = $.get('captchas', []); - while ((captcha = captchas[0]) && captcha.time < Date.now()) { - captchas.shift(); - } - if (captcha = captchas.shift()) { - challenge = captcha.challenge; - response = captcha.response; - } else { - challenge = QR.captcha.nodes.img.alt; - if (response = QR.captcha.nodes.input.value) { - QR.captcha.reload(); - } - } - $.set('captchas', captchas); - QR.captcha.count(captchas); + _ref1 = QR.captcha.getOne(), challenge = _ref1.challenge, response = _ref1.response; if (!response) { err = 'No valid captcha.'; - } else { - response = response.trim(); - if (!/\s/.test(response)) { - response = "" + response + " " + response; - } } } if (err) { @@ -6620,7 +6643,7 @@ if (/mistyped/i.test(err.textContent)) { err = 'Error: You seem to have mistyped the CAPTCHA.'; } - QR.cooldown.auto = QR.captcha.isEnabled ? !!$.get('captchas', []).length : err === 'Connection error with sys.4chan.org.' ? true : false; + QR.cooldown.auto = QR.captcha.isEnabled ? !!QR.captcha.captchas.length : err === 'Connection error with sys.4chan.org.' ? true : false; QR.cooldown.set({ delay: 2 }); diff --git a/src/qr.coffee b/src/qr.coffee index b0b312a66..f00e29232 100644 --- a/src/qr.coffee +++ b/src/qr.coffee @@ -496,7 +496,7 @@ QR = index = QR.replies.indexOf @ if QR.replies.length is 1 new QR.reply().select() - else if @el.id is 'selected' + else if @ is QR.selected (QR.replies[index-1] or QR.replies[index+1]).select() QR.replies.splice index, 1 return unless window.URL @@ -531,26 +531,47 @@ QR = $.on imgContainer, 'click', @reload.bind @ $.on @nodes.input, 'keydown', @keydown.bind @ - $.sync 'captchas', @count.bind @ - @count $.get 'captchas', [] + $.sync 'captchas', @sync.bind @ + @sync $.get 'captchas', [] # start with an uncached captcha @reload() $.addClass QR.nodes.el, 'has-captcha' $.after QR.nodes.com.parentNode, [imgContainer, inputContainer] + sync: (@captchas) -> + @count() + getOne: -> + @clear() + if captcha = @captchas.shift() + {challenge, response} = captcha + @count() + $.set 'captchas', @captchas + else + challenge = @nodes.img.alt + if response = @nodes.input.value then @reload() + if response + response = response.trim() + # one-word-captcha: + # If there's only one word, duplicate it. + response = "#{response} #{response}" unless /\s/.test response + {challenge, response} save: -> return unless response = @nodes.input.value.trim() - captchas = $.get 'captchas', [] - # Remove old captchas. - while (captcha = captchas[0]) and captcha.time < Date.now() - captchas.shift() - captchas.push + @captchas.push challenge: @nodes.challenge.firstChild.value response: response - time: @timeout - $.set 'captchas', captchas - @count captchas + timeout: @timeout + @count() @reload() + $.set 'captchas', @captchas + clear: -> + now = Date.now() + for captcha, i in @captchas + break if captcha.timeout > now + return unless i + @captchas = @captchas[i..] + @count() + $.set 'captchas', @captchas load: -> # -1 minute to give upload some time. @timeout = Date.now() + $.unsafeWindow.RecaptchaState.timeout * $.SECOND - $.MINUTE @@ -558,8 +579,9 @@ QR = @nodes.img.alt = challenge @nodes.img.src = "//www.google.com/recaptcha/api/image?c=#{challenge}" @nodes.input.value = null - count: (arr) -> - count = arr.length + @clear() + count: -> + count = @captchas.length @nodes.input.placeholder = switch count when 0 'Verification (Shift + Enter to cache)' @@ -709,26 +731,8 @@ QR = err = 'No file selected.' if QR.captcha.isEnabled and !err - # get oldest valid captcha - captchas = $.get 'captchas', [] - # remove old captchas - while (captcha = captchas[0]) and captcha.time < Date.now() - captchas.shift() - if captcha = captchas.shift() - challenge = captcha.challenge - response = captcha.response - else - challenge = QR.captcha.nodes.img.alt - if response = QR.captcha.nodes.input.value then QR.captcha.reload() - $.set 'captchas', captchas - QR.captcha.count captchas - unless response - err = 'No valid captcha.' - else - response = response.trim() - # one-word-captcha: - # If there's only one word, duplicate it. - response = "#{response} #{response}" unless /\s/.test response + {challenge, response} = QR.captcha.getOne() + err = 'No valid captcha.' unless response if err # stop auto-posting @@ -818,7 +822,7 @@ QR = err = 'Error: You seem to have mistyped the CAPTCHA.' # Enable auto-post if we have some cached captchas. QR.cooldown.auto = if QR.captcha.isEnabled - !!$.get('captchas', []).length + !!QR.captcha.captchas.length else if err is 'Connection error with sys.4chan.org.' true else