From 208e0b071cd0ea5cea9e8390a45767bf874d75db Mon Sep 17 00:00:00 2001 From: James Campos Date: Wed, 10 Aug 2011 19:22:50 -0700 Subject: [PATCH] persistent captchas --- 4chan_x.user.js | 49 ++++++++++++++++++++++++++++++++----------------- script.coffee | 40 ++++++++++++++++++++++++++++++---------- 2 files changed, 62 insertions(+), 27 deletions(-) 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
" + spoiler + "
" + qr.captcha.length + " captcha cached
attach another file
"; + html = " X
Quick Reply
" + spoiler + "
" + ($.getValue('captcha', []).length) + " captcha cached
attach another file
"; 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
attach another file
@@ -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}/", {}