diff --git a/CHANGELOG.md b/CHANGELOG.md index 4379584f7..f2263db28 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ The links to individual versions below are to copies of the script with the upda ## v1.11.0 +**v1.11.0.7** *(2015-06-21)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.0.7/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.0.7/builds/4chan-X-noupdate.crx "Chromium version")] +- Add `Use Recaptcha v1` option to use the old text-based captchas in the Quick Reply. + **v1.11.0.6** *(2015-06-20)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.0.6/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.0.6/builds/4chan-X-noupdate.crx "Chromium version")] - Support toggling images in the captcha with the number keys (as arranged in the numpad) and the UIOJKLM,. keys. - Arrow key navigation now works in noscript captcha. diff --git a/builds/4chan-X-beta.crx b/builds/4chan-X-beta.crx index 9bfbaa0d9..df1d14615 100644 Binary files a/builds/4chan-X-beta.crx and b/builds/4chan-X-beta.crx differ diff --git a/builds/4chan-X-beta.meta.js b/builds/4chan-X-beta.meta.js index 6b927ebda..63a668f0f 100644 --- a/builds/4chan-X-beta.meta.js +++ b/builds/4chan-X-beta.meta.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X beta -// @version 1.11.0.6 +// @version 1.11.0.7 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X diff --git a/builds/4chan-X-beta.user.js b/builds/4chan-X-beta.user.js index bd2c64c83..db361c661 100644 --- a/builds/4chan-X-beta.user.js +++ b/builds/4chan-X-beta.user.js @@ -1,7 +1,7 @@ // Generated by CoffeeScript // ==UserScript== // @name 4chan X beta -// @version 1.11.0.6 +// @version 1.11.0.7 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -233,6 +233,7 @@ 'Hide Original Post Form': [true, 'Hide the normal post form.', 1], 'Cooldown': [true, 'Indicate the remaining time before posting again.', 1], 'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.', 1], + 'Use Recaptcha v1': [false, 'Use the old text version of Recaptcha.', 1], 'Force Noscript Captcha': [false, 'Use the non-Javascript fallback captcha in the QR even if Javascript is enabled.', 1], 'Auto-load captcha': [false, 'Automatically load the captcha in the QR even if your post is empty.', 1], 'Post on Captcha Completion': [false, 'Submit the post immediately when the captcha is completed.', 1], @@ -400,7 +401,7 @@ doc = d.documentElement; g = { - VERSION: '1.11.0.6', + VERSION: '1.11.0.7', NAMESPACE: '4chan X.', boards: {} }; @@ -6671,7 +6672,7 @@ QR = { mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'], init: function() { - var sc; + var sc, version; if (!Conf['Quick Reply']) { return; } @@ -6680,7 +6681,8 @@ if (g.VIEW === 'archive') { return; } - this.captcha = Captcha.v2; + version = Conf['Use Recaptcha v1'] ? 'v1' : 'v2'; + this.captcha = Captcha[version]; $.on(d, '4chanXInitFinished', this.initReady); Post.callbacks.push({ name: 'Quick Reply', @@ -7456,7 +7458,12 @@ }; cb = function(response) { if (response != null) { - extra.form.append('g-recaptcha-response', response); + if (response.challenge != null) { + extra.form.append('recaptcha_challenge_field', response.challenge); + extra.form.append('recaptcha_response_field', response.response); + } else { + extra.form.append('g-recaptcha-response', response); + } } QR.req = $.ajax("https://sys.4chan.org/" + g.BOARD + "/post", options, extra); return QR.req.progress = '...'; @@ -7790,6 +7797,172 @@ } }; + Captcha.v1 = { + init: function() { + var captchaContainer, imgContainer, input, script; + if (d.cookie.indexOf('pass_enabled=1') >= 0) { + return; + } + if (!(this.isEnabled = !!$.id('g-recaptcha'))) { + return; + } + script = $.el('script', { + src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js' + }); + $.add(d.head, script); + captchaContainer = $.el('div', { + id: 'captchaContainer', + hidden: true + }); + $.add(d.body, captchaContainer); + imgContainer = $.el('div', { + className: 'captcha-img', + title: 'Reload reCAPTCHA' + }); + $.extend(imgContainer, { + innerHTML: "" + }); + input = $.el('input', { + className: 'captcha-input field', + title: 'Verification', + autocomplete: 'off', + spellcheck: false + }); + this.nodes = { + img: imgContainer.firstChild, + input: input + }; + $.on(input, 'blur', QR.focusout); + $.on(input, 'focus', QR.focusin); + $.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha)); + $.on(this.nodes.img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha)); + $.addClass(QR.nodes.el, 'has-captcha'); + $.after(QR.nodes.com.parentNode, [imgContainer, input]); + this.captchas = []; + new MutationObserver(this.afterSetup).observe($.id('captchaContainer'), { + childList: true + }); + this.beforeSetup(); + if (Conf['Auto-load captcha']) { + return this.setup(); + } + }, + cb: { + focus: function() { + return QR.captcha.setup(false, true); + } + }, + beforeSetup: function() { + var img, input, ref; + ref = this.nodes, img = ref.img, input = ref.input; + img.parentNode.hidden = true; + input.value = ''; + input.placeholder = 'Focus to load reCAPTCHA'; + return $.on(input, 'focus click', this.cb.focus); + }, + needed: function() { + var captchaCount, postsCount; + captchaCount = this.captchas.length; + if (QR.req) { + captchaCount++; + } + postsCount = QR.posts.length; + if (postsCount === 1 && !Conf['Auto-load captcha'] && !QR.posts[0].com && !QR.posts[0].file) { + postsCount = 0; + } + return captchaCount < postsCount; + }, + onNewPost: function() {}, + onPostChange: function() {}, + setup: function(focus, force) { + if (!(this.isEnabled && (this.needed() || force))) { + return; + } + $.globalEval('(function() {\n var captchaContainer = document.getElementById("captchaContainer");\n if (captchaContainer.firstChild) return;\n function setup() {\n if (window.Recaptcha) {\n Recaptcha.create(recaptchaKey, captchaContainer, {theme: "clean"});\n } else {\n setTimeout(setup, 25);\n }\n }\n setup();\n})()'); + if (focus) { + return this.nodes.input.focus(); + } + }, + afterSetup: function() { + var challenge, img, input, ref, setLifetime; + if (!(challenge = $.id('recaptcha_challenge_field_holder'))) { + return; + } + if (challenge === QR.captcha.nodes.challenge) { + return; + } + setLifetime = function(e) { + return QR.captcha.lifetime = e.detail; + }; + $.on(window, 'captcha:timeout', setLifetime); + $.globalEval('window.dispatchEvent(new CustomEvent("captcha:timeout", {detail: RecaptchaState.timeout}))'); + $.off(window, 'captcha:timeout', setLifetime); + ref = QR.captcha.nodes, img = ref.img, input = ref.input; + img.parentNode.hidden = false; + input.placeholder = 'Verification'; + $.off(input, 'focus click', QR.captcha.cb.focus); + QR.captcha.nodes.challenge = challenge; + new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, { + childList: true, + subtree: true, + attributes: true + }); + QR.captcha.load(); + if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { + QR.nodes.el.style.top = null; + return QR.nodes.el.style.bottom = '0px'; + } + }, + destroy: function() { + if (!this.isEnabled) { + return; + } + $.globalEval('Recaptcha.destroy()'); + return this.beforeSetup(); + }, + getOne: function() { + var challenge, response; + challenge = this.nodes.img.alt; + if (/\S/.test(response = this.nodes.input.value)) { + this.destroy(); + return { + challenge: challenge, + response: response + }; + } else { + return null; + } + }, + load: function() { + var challenge, challenge_image; + if (!this.nodes.challenge.firstChild) { + return; + } + if (!(challenge_image = $.id('recaptcha_challenge_image'))) { + return; + } + this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE; + challenge = this.nodes.challenge.firstChild.value; + this.nodes.img.alt = challenge; + this.nodes.img.src = challenge_image.src; + return this.nodes.input.value = null; + }, + reload: function(focus) { + $.globalEval('Recaptcha.reload(); Recaptcha.should_focus = false;'); + if (focus) { + return this.nodes.input.focus(); + } + }, + keydown: function(e) { + if (e.keyCode === 8 && !this.nodes.input.value) { + this.reload(); + } else { + return; + } + return e.preventDefault(); + } + }; + Captcha.v2 = { lifetime: 2 * $.MINUTE, init: function() { @@ -18280,6 +18453,7 @@ "#qr > form {\n" + " max-height: calc(100vh - 75px);\n" + " overflow-y: auto;\n" + +" overflow-x: hidden;\n" + "}\n" + "#qrtab {\n" + " border-radius: 3px 3px 0 0;\n" + @@ -18352,7 +18526,20 @@ " position: relative;\n" + " top: 2px;\n" + "}\n" + -"/* Captcha */\n" + +"/* Recaptcha v1 */\n" + +".captcha-img {\n" + +" margin: 0px;\n" + +" text-align: center;\n" + +" background-image: #fff;\n" + +" font-size: 0px;\n" + +" min-height: 59px;\n" + +" min-width: 302px;\n" + +"}\n" + +".captcha-input{\n" + +" width: 100%;\n" + +" margin: 1px 0 0;\n" + +"}\n" + +"/* Recaptcha v2 */\n" + "#qr .captcha-root {\n" + " position: relative;\n" + "}\n" + diff --git a/builds/4chan-X-noupdate.crx b/builds/4chan-X-noupdate.crx index c0da5c73a..5f87d0f0b 100644 Binary files a/builds/4chan-X-noupdate.crx and b/builds/4chan-X-noupdate.crx differ diff --git a/builds/4chan-X-noupdate.user.js b/builds/4chan-X-noupdate.user.js index af7e124d4..364c59861 100644 --- a/builds/4chan-X-noupdate.user.js +++ b/builds/4chan-X-noupdate.user.js @@ -1,7 +1,7 @@ // Generated by CoffeeScript // ==UserScript== // @name 4chan X -// @version 1.11.0.6 +// @version 1.11.0.7 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -232,6 +232,7 @@ 'Hide Original Post Form': [true, 'Hide the normal post form.', 1], 'Cooldown': [true, 'Indicate the remaining time before posting again.', 1], 'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.', 1], + 'Use Recaptcha v1': [false, 'Use the old text version of Recaptcha.', 1], 'Force Noscript Captcha': [false, 'Use the non-Javascript fallback captcha in the QR even if Javascript is enabled.', 1], 'Auto-load captcha': [false, 'Automatically load the captcha in the QR even if your post is empty.', 1], 'Post on Captcha Completion': [false, 'Submit the post immediately when the captcha is completed.', 1], @@ -399,7 +400,7 @@ doc = d.documentElement; g = { - VERSION: '1.11.0.6', + VERSION: '1.11.0.7', NAMESPACE: '4chan X.', boards: {} }; @@ -6670,7 +6671,7 @@ QR = { mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'], init: function() { - var sc; + var sc, version; if (!Conf['Quick Reply']) { return; } @@ -6679,7 +6680,8 @@ if (g.VIEW === 'archive') { return; } - this.captcha = Captcha.v2; + version = Conf['Use Recaptcha v1'] ? 'v1' : 'v2'; + this.captcha = Captcha[version]; $.on(d, '4chanXInitFinished', this.initReady); Post.callbacks.push({ name: 'Quick Reply', @@ -7455,7 +7457,12 @@ }; cb = function(response) { if (response != null) { - extra.form.append('g-recaptcha-response', response); + if (response.challenge != null) { + extra.form.append('recaptcha_challenge_field', response.challenge); + extra.form.append('recaptcha_response_field', response.response); + } else { + extra.form.append('g-recaptcha-response', response); + } } QR.req = $.ajax("https://sys.4chan.org/" + g.BOARD + "/post", options, extra); return QR.req.progress = '...'; @@ -7789,6 +7796,172 @@ } }; + Captcha.v1 = { + init: function() { + var captchaContainer, imgContainer, input, script; + if (d.cookie.indexOf('pass_enabled=1') >= 0) { + return; + } + if (!(this.isEnabled = !!$.id('g-recaptcha'))) { + return; + } + script = $.el('script', { + src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js' + }); + $.add(d.head, script); + captchaContainer = $.el('div', { + id: 'captchaContainer', + hidden: true + }); + $.add(d.body, captchaContainer); + imgContainer = $.el('div', { + className: 'captcha-img', + title: 'Reload reCAPTCHA' + }); + $.extend(imgContainer, { + innerHTML: "" + }); + input = $.el('input', { + className: 'captcha-input field', + title: 'Verification', + autocomplete: 'off', + spellcheck: false + }); + this.nodes = { + img: imgContainer.firstChild, + input: input + }; + $.on(input, 'blur', QR.focusout); + $.on(input, 'focus', QR.focusin); + $.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha)); + $.on(this.nodes.img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha)); + $.addClass(QR.nodes.el, 'has-captcha'); + $.after(QR.nodes.com.parentNode, [imgContainer, input]); + this.captchas = []; + new MutationObserver(this.afterSetup).observe($.id('captchaContainer'), { + childList: true + }); + this.beforeSetup(); + if (Conf['Auto-load captcha']) { + return this.setup(); + } + }, + cb: { + focus: function() { + return QR.captcha.setup(false, true); + } + }, + beforeSetup: function() { + var img, input, ref; + ref = this.nodes, img = ref.img, input = ref.input; + img.parentNode.hidden = true; + input.value = ''; + input.placeholder = 'Focus to load reCAPTCHA'; + return $.on(input, 'focus click', this.cb.focus); + }, + needed: function() { + var captchaCount, postsCount; + captchaCount = this.captchas.length; + if (QR.req) { + captchaCount++; + } + postsCount = QR.posts.length; + if (postsCount === 1 && !Conf['Auto-load captcha'] && !QR.posts[0].com && !QR.posts[0].file) { + postsCount = 0; + } + return captchaCount < postsCount; + }, + onNewPost: function() {}, + onPostChange: function() {}, + setup: function(focus, force) { + if (!(this.isEnabled && (this.needed() || force))) { + return; + } + $.globalEval('(function() {\n var captchaContainer = document.getElementById("captchaContainer");\n if (captchaContainer.firstChild) return;\n function setup() {\n if (window.Recaptcha) {\n Recaptcha.create(recaptchaKey, captchaContainer, {theme: "clean"});\n } else {\n setTimeout(setup, 25);\n }\n }\n setup();\n})()'); + if (focus) { + return this.nodes.input.focus(); + } + }, + afterSetup: function() { + var challenge, img, input, ref, setLifetime; + if (!(challenge = $.id('recaptcha_challenge_field_holder'))) { + return; + } + if (challenge === QR.captcha.nodes.challenge) { + return; + } + setLifetime = function(e) { + return QR.captcha.lifetime = e.detail; + }; + $.on(window, 'captcha:timeout', setLifetime); + $.globalEval('window.dispatchEvent(new CustomEvent("captcha:timeout", {detail: RecaptchaState.timeout}))'); + $.off(window, 'captcha:timeout', setLifetime); + ref = QR.captcha.nodes, img = ref.img, input = ref.input; + img.parentNode.hidden = false; + input.placeholder = 'Verification'; + $.off(input, 'focus click', QR.captcha.cb.focus); + QR.captcha.nodes.challenge = challenge; + new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, { + childList: true, + subtree: true, + attributes: true + }); + QR.captcha.load(); + if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { + QR.nodes.el.style.top = null; + return QR.nodes.el.style.bottom = '0px'; + } + }, + destroy: function() { + if (!this.isEnabled) { + return; + } + $.globalEval('Recaptcha.destroy()'); + return this.beforeSetup(); + }, + getOne: function() { + var challenge, response; + challenge = this.nodes.img.alt; + if (/\S/.test(response = this.nodes.input.value)) { + this.destroy(); + return { + challenge: challenge, + response: response + }; + } else { + return null; + } + }, + load: function() { + var challenge, challenge_image; + if (!this.nodes.challenge.firstChild) { + return; + } + if (!(challenge_image = $.id('recaptcha_challenge_image'))) { + return; + } + this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE; + challenge = this.nodes.challenge.firstChild.value; + this.nodes.img.alt = challenge; + this.nodes.img.src = challenge_image.src; + return this.nodes.input.value = null; + }, + reload: function(focus) { + $.globalEval('Recaptcha.reload(); Recaptcha.should_focus = false;'); + if (focus) { + return this.nodes.input.focus(); + } + }, + keydown: function(e) { + if (e.keyCode === 8 && !this.nodes.input.value) { + this.reload(); + } else { + return; + } + return e.preventDefault(); + } + }; + Captcha.v2 = { lifetime: 2 * $.MINUTE, init: function() { @@ -18279,6 +18452,7 @@ "#qr > form {\n" + " max-height: calc(100vh - 75px);\n" + " overflow-y: auto;\n" + +" overflow-x: hidden;\n" + "}\n" + "#qrtab {\n" + " border-radius: 3px 3px 0 0;\n" + @@ -18351,7 +18525,20 @@ " position: relative;\n" + " top: 2px;\n" + "}\n" + -"/* Captcha */\n" + +"/* Recaptcha v1 */\n" + +".captcha-img {\n" + +" margin: 0px;\n" + +" text-align: center;\n" + +" background-image: #fff;\n" + +" font-size: 0px;\n" + +" min-height: 59px;\n" + +" min-width: 302px;\n" + +"}\n" + +".captcha-input{\n" + +" width: 100%;\n" + +" margin: 1px 0 0;\n" + +"}\n" + +"/* Recaptcha v2 */\n" + "#qr .captcha-root {\n" + " position: relative;\n" + "}\n" + diff --git a/builds/4chan-X.crx b/builds/4chan-X.crx index 55623a0c3..206dfffff 100644 Binary files a/builds/4chan-X.crx and b/builds/4chan-X.crx differ diff --git a/builds/4chan-X.meta.js b/builds/4chan-X.meta.js index f5f8087d6..c83e2ea68 100644 --- a/builds/4chan-X.meta.js +++ b/builds/4chan-X.meta.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X -// @version 1.11.0.6 +// @version 1.11.0.7 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index b9841fb38..df7e98a17 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -1,7 +1,7 @@ // Generated by CoffeeScript // ==UserScript== // @name 4chan X -// @version 1.11.0.6 +// @version 1.11.0.7 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -233,6 +233,7 @@ 'Hide Original Post Form': [true, 'Hide the normal post form.', 1], 'Cooldown': [true, 'Indicate the remaining time before posting again.', 1], 'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.', 1], + 'Use Recaptcha v1': [false, 'Use the old text version of Recaptcha.', 1], 'Force Noscript Captcha': [false, 'Use the non-Javascript fallback captcha in the QR even if Javascript is enabled.', 1], 'Auto-load captcha': [false, 'Automatically load the captcha in the QR even if your post is empty.', 1], 'Post on Captcha Completion': [false, 'Submit the post immediately when the captcha is completed.', 1], @@ -400,7 +401,7 @@ doc = d.documentElement; g = { - VERSION: '1.11.0.6', + VERSION: '1.11.0.7', NAMESPACE: '4chan X.', boards: {} }; @@ -6671,7 +6672,7 @@ QR = { mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'], init: function() { - var sc; + var sc, version; if (!Conf['Quick Reply']) { return; } @@ -6680,7 +6681,8 @@ if (g.VIEW === 'archive') { return; } - this.captcha = Captcha.v2; + version = Conf['Use Recaptcha v1'] ? 'v1' : 'v2'; + this.captcha = Captcha[version]; $.on(d, '4chanXInitFinished', this.initReady); Post.callbacks.push({ name: 'Quick Reply', @@ -7456,7 +7458,12 @@ }; cb = function(response) { if (response != null) { - extra.form.append('g-recaptcha-response', response); + if (response.challenge != null) { + extra.form.append('recaptcha_challenge_field', response.challenge); + extra.form.append('recaptcha_response_field', response.response); + } else { + extra.form.append('g-recaptcha-response', response); + } } QR.req = $.ajax("https://sys.4chan.org/" + g.BOARD + "/post", options, extra); return QR.req.progress = '...'; @@ -7790,6 +7797,172 @@ } }; + Captcha.v1 = { + init: function() { + var captchaContainer, imgContainer, input, script; + if (d.cookie.indexOf('pass_enabled=1') >= 0) { + return; + } + if (!(this.isEnabled = !!$.id('g-recaptcha'))) { + return; + } + script = $.el('script', { + src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js' + }); + $.add(d.head, script); + captchaContainer = $.el('div', { + id: 'captchaContainer', + hidden: true + }); + $.add(d.body, captchaContainer); + imgContainer = $.el('div', { + className: 'captcha-img', + title: 'Reload reCAPTCHA' + }); + $.extend(imgContainer, { + innerHTML: "" + }); + input = $.el('input', { + className: 'captcha-input field', + title: 'Verification', + autocomplete: 'off', + spellcheck: false + }); + this.nodes = { + img: imgContainer.firstChild, + input: input + }; + $.on(input, 'blur', QR.focusout); + $.on(input, 'focus', QR.focusin); + $.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha)); + $.on(this.nodes.img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha)); + $.addClass(QR.nodes.el, 'has-captcha'); + $.after(QR.nodes.com.parentNode, [imgContainer, input]); + this.captchas = []; + new MutationObserver(this.afterSetup).observe($.id('captchaContainer'), { + childList: true + }); + this.beforeSetup(); + if (Conf['Auto-load captcha']) { + return this.setup(); + } + }, + cb: { + focus: function() { + return QR.captcha.setup(false, true); + } + }, + beforeSetup: function() { + var img, input, ref; + ref = this.nodes, img = ref.img, input = ref.input; + img.parentNode.hidden = true; + input.value = ''; + input.placeholder = 'Focus to load reCAPTCHA'; + return $.on(input, 'focus click', this.cb.focus); + }, + needed: function() { + var captchaCount, postsCount; + captchaCount = this.captchas.length; + if (QR.req) { + captchaCount++; + } + postsCount = QR.posts.length; + if (postsCount === 1 && !Conf['Auto-load captcha'] && !QR.posts[0].com && !QR.posts[0].file) { + postsCount = 0; + } + return captchaCount < postsCount; + }, + onNewPost: function() {}, + onPostChange: function() {}, + setup: function(focus, force) { + if (!(this.isEnabled && (this.needed() || force))) { + return; + } + $.globalEval('(function() {\n var captchaContainer = document.getElementById("captchaContainer");\n if (captchaContainer.firstChild) return;\n function setup() {\n if (window.Recaptcha) {\n Recaptcha.create(recaptchaKey, captchaContainer, {theme: "clean"});\n } else {\n setTimeout(setup, 25);\n }\n }\n setup();\n})()'); + if (focus) { + return this.nodes.input.focus(); + } + }, + afterSetup: function() { + var challenge, img, input, ref, setLifetime; + if (!(challenge = $.id('recaptcha_challenge_field_holder'))) { + return; + } + if (challenge === QR.captcha.nodes.challenge) { + return; + } + setLifetime = function(e) { + return QR.captcha.lifetime = e.detail; + }; + $.on(window, 'captcha:timeout', setLifetime); + $.globalEval('window.dispatchEvent(new CustomEvent("captcha:timeout", {detail: RecaptchaState.timeout}))'); + $.off(window, 'captcha:timeout', setLifetime); + ref = QR.captcha.nodes, img = ref.img, input = ref.input; + img.parentNode.hidden = false; + input.placeholder = 'Verification'; + $.off(input, 'focus click', QR.captcha.cb.focus); + QR.captcha.nodes.challenge = challenge; + new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, { + childList: true, + subtree: true, + attributes: true + }); + QR.captcha.load(); + if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { + QR.nodes.el.style.top = null; + return QR.nodes.el.style.bottom = '0px'; + } + }, + destroy: function() { + if (!this.isEnabled) { + return; + } + $.globalEval('Recaptcha.destroy()'); + return this.beforeSetup(); + }, + getOne: function() { + var challenge, response; + challenge = this.nodes.img.alt; + if (/\S/.test(response = this.nodes.input.value)) { + this.destroy(); + return { + challenge: challenge, + response: response + }; + } else { + return null; + } + }, + load: function() { + var challenge, challenge_image; + if (!this.nodes.challenge.firstChild) { + return; + } + if (!(challenge_image = $.id('recaptcha_challenge_image'))) { + return; + } + this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE; + challenge = this.nodes.challenge.firstChild.value; + this.nodes.img.alt = challenge; + this.nodes.img.src = challenge_image.src; + return this.nodes.input.value = null; + }, + reload: function(focus) { + $.globalEval('Recaptcha.reload(); Recaptcha.should_focus = false;'); + if (focus) { + return this.nodes.input.focus(); + } + }, + keydown: function(e) { + if (e.keyCode === 8 && !this.nodes.input.value) { + this.reload(); + } else { + return; + } + return e.preventDefault(); + } + }; + Captcha.v2 = { lifetime: 2 * $.MINUTE, init: function() { @@ -18280,6 +18453,7 @@ "#qr > form {\n" + " max-height: calc(100vh - 75px);\n" + " overflow-y: auto;\n" + +" overflow-x: hidden;\n" + "}\n" + "#qrtab {\n" + " border-radius: 3px 3px 0 0;\n" + @@ -18352,7 +18526,20 @@ " position: relative;\n" + " top: 2px;\n" + "}\n" + -"/* Captcha */\n" + +"/* Recaptcha v1 */\n" + +".captcha-img {\n" + +" margin: 0px;\n" + +" text-align: center;\n" + +" background-image: #fff;\n" + +" font-size: 0px;\n" + +" min-height: 59px;\n" + +" min-width: 302px;\n" + +"}\n" + +".captcha-input{\n" + +" width: 100%;\n" + +" margin: 1px 0 0;\n" + +"}\n" + +"/* Recaptcha v2 */\n" + "#qr .captcha-root {\n" + " position: relative;\n" + "}\n" + diff --git a/builds/4chan-X.zip b/builds/4chan-X.zip index 32aaa06aa..7f9577dbc 100644 Binary files a/builds/4chan-X.zip and b/builds/4chan-X.zip differ diff --git a/builds/updates-beta.xml b/builds/updates-beta.xml index a4e215c31..9d143416a 100644 --- a/builds/updates-beta.xml +++ b/builds/updates-beta.xml @@ -1,7 +1,7 @@ - + diff --git a/builds/updates.xml b/builds/updates.xml index c9952f5c6..36ea57ded 100644 --- a/builds/updates.xml +++ b/builds/updates.xml @@ -1,7 +1,7 @@ - + diff --git a/package.json b/package.json index 150be93eb..f62a0cbe2 100755 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "description": "Cross-browser userscript for maximum lurking on 4chan.", "meta": { "name": "4chan X", - "version": "1.11.0.6", - "date": "2015-06-21T06:05:51.745Z", + "version": "1.11.0.7", + "date": "2015-06-21T17:20:52.716Z", "repo": "https://github.com/ccd0/4chan-x/", "page": "https://github.com/ccd0/4chan-x", "downloads": "https://ccd0.github.io/4chan-x/builds/",