diff --git a/CHANGELOG.md b/CHANGELOG.md index f270b8ff3..3a7b3b904 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ ### v1.14.21 +**v1.14.21.5** *(2021-07-07)* - [[Userscript](https://raw.githubusercontent.com/ccd0/4chan-x/1.14.21.5/builds/4chan-X-noupdate.user.js)] [[Chrome extension](https://raw.githubusercontent.com/ccd0/4chan-x/1.14.21.5/builds/4chan-X-noupdate.crx)] +- Fix bug causing captcha to sometimes not work when replying from index. + +**v1.14.21.4** *(2021-07-05)* - [[Userscript](https://raw.githubusercontent.com/ccd0/4chan-x/1.14.21.4/builds/4chan-X-noupdate.user.js)] [[Chrome extension](https://raw.githubusercontent.com/ccd0/4chan-x/1.14.21.4/builds/4chan-X-noupdate.crx)] +- Preliminary support for new first-party captcha on 4chan. + **v1.14.21.3** *(2021-05-07)* - [[Userscript](https://raw.githubusercontent.com/ccd0/4chan-x/1.14.21.3/builds/4chan-X-noupdate.user.js)] [[Chrome extension](https://raw.githubusercontent.com/ccd0/4chan-x/1.14.21.3/builds/4chan-X-noupdate.crx)] - Fix race condition causing unread posts tracking to malfunction. diff --git a/builds/4chan-X-beta.crx b/builds/4chan-X-beta.crx index 31ac6ddf6..a102e1fd3 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 06d6236da..3c135b8e3 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.14.21.3 +// @version 1.14.21.5 // @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 11f69fa49..ffbd1011d 100644 --- a/builds/4chan-X-beta.user.js +++ b/builds/4chan-X-beta.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X beta -// @version 1.14.21.3 +// @version 1.14.21.5 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -218,7 +218,7 @@ docSet = function() { }; g = { - VERSION: '1.14.21.3', + VERSION: '1.14.21.5', NAMESPACE: '4chan X.', sites: Object.create(null), boards: Object.create(null) @@ -23732,6 +23732,115 @@ Captcha = {}; }).call(this); +(function() { + Captcha.t = { + init: function() { + var root; + if (d.cookie.indexOf('pass_enabled=1') >= 0) { + return; + } + if (!(this.isEnabled = !!$('#t-root') || !$.id('postForm'))) { + return; + } + root = $.el('div', { + className: 'captcha-root' + }); + this.nodes = { + root: root + }; + $.addClass(QR.nodes.el, 'has-captcha', 'captcha-t'); + return $.after(QR.nodes.com.parentNode, root); + }, + moreNeeded: function() {}, + getThread: function() { + var boardID, threadID; + boardID = g.BOARD.ID; + if (QR.posts[0].thread === 'new') { + threadID = '0'; + } else { + threadID = '' + QR.posts[0].thread; + } + return { + boardID: boardID, + threadID: threadID + }; + }, + setup: function(focus) { + if (!this.isEnabled) { + return; + } + if (!this.nodes.container) { + this.nodes.container = $.el('div', { + className: 'captcha-container' + }); + $.prepend(this.nodes.root, this.nodes.container); + Captcha.t.currentThread = Captcha.t.getThread(); + $.global(function() { + var el; + el = document.querySelector('#qr .captcha-container'); + window.TCaptcha.init(el, this.boardID, +this.threadID); + return window.TCaptcha.setErrorCb(function(err) { + return window.dispatchEvent(new CustomEvent('CreateNotification', { + detail: { + type: 'warning', + content: '' + err + } + })); + }); + }, Captcha.t.currentThread); + } + if (focus) { + return $('#t-resp').focus(); + } + }, + destroy: function() { + if (!(this.isEnabled && this.nodes.container)) { + return; + } + $.global(function() { + return window.TCaptcha.destroy(); + }); + $.rm(this.nodes.container); + return delete this.nodes.container; + }, + updateThread: function() { + var boardID, newThread, ref, threadID; + ref = Captcha.t.currentThread, boardID = ref.boardID, threadID = ref.threadID; + newThread = Captcha.t.getThread(); + if (!(newThread.boardID === boardID && newThread.threadID === threadID)) { + Captcha.t.destroy(); + return Captcha.t.setup(); + } + }, + getOne: function() { + var i, key, len, ref, response; + response = {}; + if (this.nodes.container) { + ref = ['t-response', 't-challenge']; + for (i = 0, len = ref.length; i < len; i++) { + key = ref[i]; + response[key] = $("[name='" + key + "']", this.nodes.container).value; + } + } + if (!response['t-response']) { + response = null; + } + return response; + }, + setUsed: function() { + if (this.nodes.container) { + return $.global(function() { + return window.TCaptcha.clearChallenge(); + }); + } + }, + occupied: function() { + return !!this.nodes.container; + } + }; + +}).call(this); + (function() { var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; @@ -24158,7 +24267,6 @@ QR = (function() { return; } this.posts = []; - this.captcha = Captcha.v2; $.on(d, '4chanXInitFinished', function() { return BoardConfig.ready(QR.initReady); }); @@ -24186,7 +24294,9 @@ QR = (function() { return Header.addShortcut('qr', sc, 540); }, initReady: function() { - var config, link, linkBot, navLinksBot, origToggle, prop; + var captchaVersion, config, link, linkBot, navLinksBot, origToggle, prop; + captchaVersion = $('#t-root') ? 't' : 'v2'; + QR.captcha = Captcha[captchaVersion]; QR.postingIsEnabled = true; config = g.BOARD.config; prop = function(key, def) { @@ -24964,8 +25074,11 @@ QR = (function() { if (g.BOARD.ID === 'r9k' && !((ref = post.com) != null ? ref.match(/[a-z-]/i) : void 0)) { err || (err = 'Original comment required.'); } - if (QR.captcha.isEnabled && !(/\b_ct=/.test(d.cookie) && threadID) && !(err && !force)) { - captcha = QR.captcha.getOne(!!threadID) || Captcha.cache.request(!!threadID); + if (QR.captcha.isEnabled && !(QR.captcha === Captcha.v2 && /\b_ct=/.test(d.cookie) && threadID) && !(err && !force)) { + captcha = QR.captcha.getOne(!!threadID); + if (QR.captcha === Captcha.v2) { + captcha || (captcha = Captcha.cache.request(!!threadID)); + } if (!captcha) { err = 'No valid captcha.'; QR.captcha.setup(!QR.cooldown.auto || d.activeElement === QR.nodes.status); @@ -25015,13 +25128,21 @@ QR = (function() { }; } cb = function(response) { + var key, val; if (response != null) { QR.currentCaptcha = response; - if (response.challenge != null) { - options.form.append('recaptcha_challenge_field', response.challenge); - options.form.append('recaptcha_response_field', response.response); + if (QR.captcha === Captcha.v2) { + if (response.challenge != null) { + options.form.append('recaptcha_challenge_field', response.challenge); + options.form.append('recaptcha_response_field', response.response); + } else { + options.form.append('g-recaptcha-response', response.response); + } } else { - options.form.append('g-recaptcha-response', response.response); + for (key in response) { + val = response[key]; + options.form.append(key, val); + } } } QR.req = $.ajax("https://sys." + (location.hostname.split('.')[1]) + ".org/" + g.BOARD + "/post", options); @@ -25031,12 +25152,14 @@ QR = (function() { QR.req = { progress: '...', abort: function() { - Captcha.cache.abort(); + if (QR.captcha === Captcha.v2) { + Captcha.cache.abort(); + } return cb = null; } }; captcha(function(response) { - if (Captcha.cache.haveCookie()) { + if (QR.captcha === Captcha.v2 && Captcha.cache.haveCookie()) { if (typeof cb === "function") { cb(); } @@ -25058,7 +25181,7 @@ QR = (function() { return QR.status(); }, response: function() { - var URL, _, connErr, err, h1, isReply, j, lastPostToThread, len, m, mi, open, post, postID, postsCount, ref, ref1, ref2, ref3, seconds, threadID; + var URL, _, base, connErr, err, h1, isReply, j, lastPostToThread, len, m, mi, open, post, postID, postsCount, ref, ref1, ref2, ref3, seconds, threadID; if (this !== QR.req) { return; } @@ -25071,12 +25194,17 @@ QR = (function() { } } else if ((connErr = !this.response || this.response.title !== 'Post successful!')) { err = QR.connectionError(); - if (QR.currentCaptcha) { + if (QR.captcha === Captcha.v2 && QR.currentCaptcha) { Captcha.cache.save(QR.currentCaptcha); } } else if (this.status !== 200) { err = "Error " + this.statusText + " (" + this.status + ")"; } + if (!connErr) { + if (typeof (base = QR.captcha).setUsed === "function") { + base.setUsed(); + } + } delete QR.currentCaptcha; if (err) { QR.errorCount = (QR.errorCount || 0) + 1; @@ -25197,7 +25325,7 @@ QR = (function() { if ((oldReq = QR.req) && !QR.req.isUploadFinished) { delete QR.req; oldReq.abort(); - if (QR.currentCaptcha) { + if (QR.captcha === Captcha.v2 && QR.currentCaptcha) { Captcha.cache.save(QR.currentCaptcha); } delete QR.currentCaptcha; @@ -25853,7 +25981,7 @@ QR = (function() { } _Class.prototype.rm = function() { - var index; + var base, index; this["delete"](); index = QR.posts.indexOf(this); if (QR.posts.length === 1) { @@ -25863,7 +25991,8 @@ QR = (function() { (QR.posts[index - 1] || QR.posts[index + 1]).select(); } QR.posts.splice(index, 1); - return QR.status(); + QR.status(); + return typeof (base = QR.captcha).updateThread === "function" ? base.updateThread() : void 0; }; _Class.prototype["delete"] = function() { @@ -25928,7 +26057,7 @@ QR = (function() { }; _Class.prototype.save = function(input, forced) { - var name, prev; + var base, name, prev; if (input.type === 'checkbox') { this.spoiler = input.checked; return; @@ -25943,6 +26072,9 @@ QR = (function() { case 'thread': (this.thread !== 'new' ? $.addClass : $.rmClass)(QR.nodes.el, 'reply-to-thread'); QR.status(); + if (typeof (base = QR.captcha).updateThread === "function") { + base.updateThread(); + } break; case 'com': this.updateComment(); @@ -26003,7 +26135,9 @@ QR = (function() { } this.nodes.span.textContent = this.com; QR.captcha.moreNeeded(); - return Captcha.cache.prerequest(); + if (QR.captcha === Captcha.v2) { + return Captcha.cache.prerequest(); + } }; _Class.prototype.isOnlyQuotes = function() { @@ -26335,7 +26469,7 @@ QR = (function() { }; _Class.prototype.drop = function() { - var el, index, newIndex, oldIndex, post; + var base, el, index, newIndex, oldIndex, post; $.rmClass(this, 'over'); if (!this.draggable) { return; @@ -26352,7 +26486,8 @@ QR = (function() { (oldIndex < newIndex ? $.after : $.before)(this, el); post = QR.posts.splice(oldIndex, 1)[0]; QR.posts.splice(newIndex, 0, post); - return QR.status(); + QR.status(); + return typeof (base = QR.captcha).updateThread === "function" ? base.updateThread() : void 0; }; return _Class; diff --git a/builds/4chan-X-noupdate.crx b/builds/4chan-X-noupdate.crx index b639cca4e..5e06564da 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 4258ca1ab..f3a1df160 100644 --- a/builds/4chan-X-noupdate.user.js +++ b/builds/4chan-X-noupdate.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X -// @version 1.14.21.3 +// @version 1.14.21.5 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -218,7 +218,7 @@ docSet = function() { }; g = { - VERSION: '1.14.21.3', + VERSION: '1.14.21.5', NAMESPACE: '4chan X.', sites: Object.create(null), boards: Object.create(null) @@ -23732,6 +23732,115 @@ Captcha = {}; }).call(this); +(function() { + Captcha.t = { + init: function() { + var root; + if (d.cookie.indexOf('pass_enabled=1') >= 0) { + return; + } + if (!(this.isEnabled = !!$('#t-root') || !$.id('postForm'))) { + return; + } + root = $.el('div', { + className: 'captcha-root' + }); + this.nodes = { + root: root + }; + $.addClass(QR.nodes.el, 'has-captcha', 'captcha-t'); + return $.after(QR.nodes.com.parentNode, root); + }, + moreNeeded: function() {}, + getThread: function() { + var boardID, threadID; + boardID = g.BOARD.ID; + if (QR.posts[0].thread === 'new') { + threadID = '0'; + } else { + threadID = '' + QR.posts[0].thread; + } + return { + boardID: boardID, + threadID: threadID + }; + }, + setup: function(focus) { + if (!this.isEnabled) { + return; + } + if (!this.nodes.container) { + this.nodes.container = $.el('div', { + className: 'captcha-container' + }); + $.prepend(this.nodes.root, this.nodes.container); + Captcha.t.currentThread = Captcha.t.getThread(); + $.global(function() { + var el; + el = document.querySelector('#qr .captcha-container'); + window.TCaptcha.init(el, this.boardID, +this.threadID); + return window.TCaptcha.setErrorCb(function(err) { + return window.dispatchEvent(new CustomEvent('CreateNotification', { + detail: { + type: 'warning', + content: '' + err + } + })); + }); + }, Captcha.t.currentThread); + } + if (focus) { + return $('#t-resp').focus(); + } + }, + destroy: function() { + if (!(this.isEnabled && this.nodes.container)) { + return; + } + $.global(function() { + return window.TCaptcha.destroy(); + }); + $.rm(this.nodes.container); + return delete this.nodes.container; + }, + updateThread: function() { + var boardID, newThread, ref, threadID; + ref = Captcha.t.currentThread, boardID = ref.boardID, threadID = ref.threadID; + newThread = Captcha.t.getThread(); + if (!(newThread.boardID === boardID && newThread.threadID === threadID)) { + Captcha.t.destroy(); + return Captcha.t.setup(); + } + }, + getOne: function() { + var i, key, len, ref, response; + response = {}; + if (this.nodes.container) { + ref = ['t-response', 't-challenge']; + for (i = 0, len = ref.length; i < len; i++) { + key = ref[i]; + response[key] = $("[name='" + key + "']", this.nodes.container).value; + } + } + if (!response['t-response']) { + response = null; + } + return response; + }, + setUsed: function() { + if (this.nodes.container) { + return $.global(function() { + return window.TCaptcha.clearChallenge(); + }); + } + }, + occupied: function() { + return !!this.nodes.container; + } + }; + +}).call(this); + (function() { var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; @@ -24158,7 +24267,6 @@ QR = (function() { return; } this.posts = []; - this.captcha = Captcha.v2; $.on(d, '4chanXInitFinished', function() { return BoardConfig.ready(QR.initReady); }); @@ -24186,7 +24294,9 @@ QR = (function() { return Header.addShortcut('qr', sc, 540); }, initReady: function() { - var config, link, linkBot, navLinksBot, origToggle, prop; + var captchaVersion, config, link, linkBot, navLinksBot, origToggle, prop; + captchaVersion = $('#t-root') ? 't' : 'v2'; + QR.captcha = Captcha[captchaVersion]; QR.postingIsEnabled = true; config = g.BOARD.config; prop = function(key, def) { @@ -24964,8 +25074,11 @@ QR = (function() { if (g.BOARD.ID === 'r9k' && !((ref = post.com) != null ? ref.match(/[a-z-]/i) : void 0)) { err || (err = 'Original comment required.'); } - if (QR.captcha.isEnabled && !(/\b_ct=/.test(d.cookie) && threadID) && !(err && !force)) { - captcha = QR.captcha.getOne(!!threadID) || Captcha.cache.request(!!threadID); + if (QR.captcha.isEnabled && !(QR.captcha === Captcha.v2 && /\b_ct=/.test(d.cookie) && threadID) && !(err && !force)) { + captcha = QR.captcha.getOne(!!threadID); + if (QR.captcha === Captcha.v2) { + captcha || (captcha = Captcha.cache.request(!!threadID)); + } if (!captcha) { err = 'No valid captcha.'; QR.captcha.setup(!QR.cooldown.auto || d.activeElement === QR.nodes.status); @@ -25015,13 +25128,21 @@ QR = (function() { }; } cb = function(response) { + var key, val; if (response != null) { QR.currentCaptcha = response; - if (response.challenge != null) { - options.form.append('recaptcha_challenge_field', response.challenge); - options.form.append('recaptcha_response_field', response.response); + if (QR.captcha === Captcha.v2) { + if (response.challenge != null) { + options.form.append('recaptcha_challenge_field', response.challenge); + options.form.append('recaptcha_response_field', response.response); + } else { + options.form.append('g-recaptcha-response', response.response); + } } else { - options.form.append('g-recaptcha-response', response.response); + for (key in response) { + val = response[key]; + options.form.append(key, val); + } } } QR.req = $.ajax("https://sys." + (location.hostname.split('.')[1]) + ".org/" + g.BOARD + "/post", options); @@ -25031,12 +25152,14 @@ QR = (function() { QR.req = { progress: '...', abort: function() { - Captcha.cache.abort(); + if (QR.captcha === Captcha.v2) { + Captcha.cache.abort(); + } return cb = null; } }; captcha(function(response) { - if (Captcha.cache.haveCookie()) { + if (QR.captcha === Captcha.v2 && Captcha.cache.haveCookie()) { if (typeof cb === "function") { cb(); } @@ -25058,7 +25181,7 @@ QR = (function() { return QR.status(); }, response: function() { - var URL, _, connErr, err, h1, isReply, j, lastPostToThread, len, m, mi, open, post, postID, postsCount, ref, ref1, ref2, ref3, seconds, threadID; + var URL, _, base, connErr, err, h1, isReply, j, lastPostToThread, len, m, mi, open, post, postID, postsCount, ref, ref1, ref2, ref3, seconds, threadID; if (this !== QR.req) { return; } @@ -25071,12 +25194,17 @@ QR = (function() { } } else if ((connErr = !this.response || this.response.title !== 'Post successful!')) { err = QR.connectionError(); - if (QR.currentCaptcha) { + if (QR.captcha === Captcha.v2 && QR.currentCaptcha) { Captcha.cache.save(QR.currentCaptcha); } } else if (this.status !== 200) { err = "Error " + this.statusText + " (" + this.status + ")"; } + if (!connErr) { + if (typeof (base = QR.captcha).setUsed === "function") { + base.setUsed(); + } + } delete QR.currentCaptcha; if (err) { QR.errorCount = (QR.errorCount || 0) + 1; @@ -25197,7 +25325,7 @@ QR = (function() { if ((oldReq = QR.req) && !QR.req.isUploadFinished) { delete QR.req; oldReq.abort(); - if (QR.currentCaptcha) { + if (QR.captcha === Captcha.v2 && QR.currentCaptcha) { Captcha.cache.save(QR.currentCaptcha); } delete QR.currentCaptcha; @@ -25853,7 +25981,7 @@ QR = (function() { } _Class.prototype.rm = function() { - var index; + var base, index; this["delete"](); index = QR.posts.indexOf(this); if (QR.posts.length === 1) { @@ -25863,7 +25991,8 @@ QR = (function() { (QR.posts[index - 1] || QR.posts[index + 1]).select(); } QR.posts.splice(index, 1); - return QR.status(); + QR.status(); + return typeof (base = QR.captcha).updateThread === "function" ? base.updateThread() : void 0; }; _Class.prototype["delete"] = function() { @@ -25928,7 +26057,7 @@ QR = (function() { }; _Class.prototype.save = function(input, forced) { - var name, prev; + var base, name, prev; if (input.type === 'checkbox') { this.spoiler = input.checked; return; @@ -25943,6 +26072,9 @@ QR = (function() { case 'thread': (this.thread !== 'new' ? $.addClass : $.rmClass)(QR.nodes.el, 'reply-to-thread'); QR.status(); + if (typeof (base = QR.captcha).updateThread === "function") { + base.updateThread(); + } break; case 'com': this.updateComment(); @@ -26003,7 +26135,9 @@ QR = (function() { } this.nodes.span.textContent = this.com; QR.captcha.moreNeeded(); - return Captcha.cache.prerequest(); + if (QR.captcha === Captcha.v2) { + return Captcha.cache.prerequest(); + } }; _Class.prototype.isOnlyQuotes = function() { @@ -26335,7 +26469,7 @@ QR = (function() { }; _Class.prototype.drop = function() { - var el, index, newIndex, oldIndex, post; + var base, el, index, newIndex, oldIndex, post; $.rmClass(this, 'over'); if (!this.draggable) { return; @@ -26352,7 +26486,8 @@ QR = (function() { (oldIndex < newIndex ? $.after : $.before)(this, el); post = QR.posts.splice(oldIndex, 1)[0]; QR.posts.splice(newIndex, 0, post); - return QR.status(); + QR.status(); + return typeof (base = QR.captcha).updateThread === "function" ? base.updateThread() : void 0; }; return _Class; diff --git a/builds/4chan-X.crx b/builds/4chan-X.crx index 30c57bd0a..e363c3fa9 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 71ec614d4..1294f04f6 100644 --- a/builds/4chan-X.meta.js +++ b/builds/4chan-X.meta.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X -// @version 1.14.21.3 +// @version 1.14.21.5 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 40e397241..28f27b257 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X -// @version 1.14.21.3 +// @version 1.14.21.5 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -218,7 +218,7 @@ docSet = function() { }; g = { - VERSION: '1.14.21.3', + VERSION: '1.14.21.5', NAMESPACE: '4chan X.', sites: Object.create(null), boards: Object.create(null) @@ -23732,6 +23732,115 @@ Captcha = {}; }).call(this); +(function() { + Captcha.t = { + init: function() { + var root; + if (d.cookie.indexOf('pass_enabled=1') >= 0) { + return; + } + if (!(this.isEnabled = !!$('#t-root') || !$.id('postForm'))) { + return; + } + root = $.el('div', { + className: 'captcha-root' + }); + this.nodes = { + root: root + }; + $.addClass(QR.nodes.el, 'has-captcha', 'captcha-t'); + return $.after(QR.nodes.com.parentNode, root); + }, + moreNeeded: function() {}, + getThread: function() { + var boardID, threadID; + boardID = g.BOARD.ID; + if (QR.posts[0].thread === 'new') { + threadID = '0'; + } else { + threadID = '' + QR.posts[0].thread; + } + return { + boardID: boardID, + threadID: threadID + }; + }, + setup: function(focus) { + if (!this.isEnabled) { + return; + } + if (!this.nodes.container) { + this.nodes.container = $.el('div', { + className: 'captcha-container' + }); + $.prepend(this.nodes.root, this.nodes.container); + Captcha.t.currentThread = Captcha.t.getThread(); + $.global(function() { + var el; + el = document.querySelector('#qr .captcha-container'); + window.TCaptcha.init(el, this.boardID, +this.threadID); + return window.TCaptcha.setErrorCb(function(err) { + return window.dispatchEvent(new CustomEvent('CreateNotification', { + detail: { + type: 'warning', + content: '' + err + } + })); + }); + }, Captcha.t.currentThread); + } + if (focus) { + return $('#t-resp').focus(); + } + }, + destroy: function() { + if (!(this.isEnabled && this.nodes.container)) { + return; + } + $.global(function() { + return window.TCaptcha.destroy(); + }); + $.rm(this.nodes.container); + return delete this.nodes.container; + }, + updateThread: function() { + var boardID, newThread, ref, threadID; + ref = Captcha.t.currentThread, boardID = ref.boardID, threadID = ref.threadID; + newThread = Captcha.t.getThread(); + if (!(newThread.boardID === boardID && newThread.threadID === threadID)) { + Captcha.t.destroy(); + return Captcha.t.setup(); + } + }, + getOne: function() { + var i, key, len, ref, response; + response = {}; + if (this.nodes.container) { + ref = ['t-response', 't-challenge']; + for (i = 0, len = ref.length; i < len; i++) { + key = ref[i]; + response[key] = $("[name='" + key + "']", this.nodes.container).value; + } + } + if (!response['t-response']) { + response = null; + } + return response; + }, + setUsed: function() { + if (this.nodes.container) { + return $.global(function() { + return window.TCaptcha.clearChallenge(); + }); + } + }, + occupied: function() { + return !!this.nodes.container; + } + }; + +}).call(this); + (function() { var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; @@ -24158,7 +24267,6 @@ QR = (function() { return; } this.posts = []; - this.captcha = Captcha.v2; $.on(d, '4chanXInitFinished', function() { return BoardConfig.ready(QR.initReady); }); @@ -24186,7 +24294,9 @@ QR = (function() { return Header.addShortcut('qr', sc, 540); }, initReady: function() { - var config, link, linkBot, navLinksBot, origToggle, prop; + var captchaVersion, config, link, linkBot, navLinksBot, origToggle, prop; + captchaVersion = $('#t-root') ? 't' : 'v2'; + QR.captcha = Captcha[captchaVersion]; QR.postingIsEnabled = true; config = g.BOARD.config; prop = function(key, def) { @@ -24964,8 +25074,11 @@ QR = (function() { if (g.BOARD.ID === 'r9k' && !((ref = post.com) != null ? ref.match(/[a-z-]/i) : void 0)) { err || (err = 'Original comment required.'); } - if (QR.captcha.isEnabled && !(/\b_ct=/.test(d.cookie) && threadID) && !(err && !force)) { - captcha = QR.captcha.getOne(!!threadID) || Captcha.cache.request(!!threadID); + if (QR.captcha.isEnabled && !(QR.captcha === Captcha.v2 && /\b_ct=/.test(d.cookie) && threadID) && !(err && !force)) { + captcha = QR.captcha.getOne(!!threadID); + if (QR.captcha === Captcha.v2) { + captcha || (captcha = Captcha.cache.request(!!threadID)); + } if (!captcha) { err = 'No valid captcha.'; QR.captcha.setup(!QR.cooldown.auto || d.activeElement === QR.nodes.status); @@ -25015,13 +25128,21 @@ QR = (function() { }; } cb = function(response) { + var key, val; if (response != null) { QR.currentCaptcha = response; - if (response.challenge != null) { - options.form.append('recaptcha_challenge_field', response.challenge); - options.form.append('recaptcha_response_field', response.response); + if (QR.captcha === Captcha.v2) { + if (response.challenge != null) { + options.form.append('recaptcha_challenge_field', response.challenge); + options.form.append('recaptcha_response_field', response.response); + } else { + options.form.append('g-recaptcha-response', response.response); + } } else { - options.form.append('g-recaptcha-response', response.response); + for (key in response) { + val = response[key]; + options.form.append(key, val); + } } } QR.req = $.ajax("https://sys." + (location.hostname.split('.')[1]) + ".org/" + g.BOARD + "/post", options); @@ -25031,12 +25152,14 @@ QR = (function() { QR.req = { progress: '...', abort: function() { - Captcha.cache.abort(); + if (QR.captcha === Captcha.v2) { + Captcha.cache.abort(); + } return cb = null; } }; captcha(function(response) { - if (Captcha.cache.haveCookie()) { + if (QR.captcha === Captcha.v2 && Captcha.cache.haveCookie()) { if (typeof cb === "function") { cb(); } @@ -25058,7 +25181,7 @@ QR = (function() { return QR.status(); }, response: function() { - var URL, _, connErr, err, h1, isReply, j, lastPostToThread, len, m, mi, open, post, postID, postsCount, ref, ref1, ref2, ref3, seconds, threadID; + var URL, _, base, connErr, err, h1, isReply, j, lastPostToThread, len, m, mi, open, post, postID, postsCount, ref, ref1, ref2, ref3, seconds, threadID; if (this !== QR.req) { return; } @@ -25071,12 +25194,17 @@ QR = (function() { } } else if ((connErr = !this.response || this.response.title !== 'Post successful!')) { err = QR.connectionError(); - if (QR.currentCaptcha) { + if (QR.captcha === Captcha.v2 && QR.currentCaptcha) { Captcha.cache.save(QR.currentCaptcha); } } else if (this.status !== 200) { err = "Error " + this.statusText + " (" + this.status + ")"; } + if (!connErr) { + if (typeof (base = QR.captcha).setUsed === "function") { + base.setUsed(); + } + } delete QR.currentCaptcha; if (err) { QR.errorCount = (QR.errorCount || 0) + 1; @@ -25197,7 +25325,7 @@ QR = (function() { if ((oldReq = QR.req) && !QR.req.isUploadFinished) { delete QR.req; oldReq.abort(); - if (QR.currentCaptcha) { + if (QR.captcha === Captcha.v2 && QR.currentCaptcha) { Captcha.cache.save(QR.currentCaptcha); } delete QR.currentCaptcha; @@ -25853,7 +25981,7 @@ QR = (function() { } _Class.prototype.rm = function() { - var index; + var base, index; this["delete"](); index = QR.posts.indexOf(this); if (QR.posts.length === 1) { @@ -25863,7 +25991,8 @@ QR = (function() { (QR.posts[index - 1] || QR.posts[index + 1]).select(); } QR.posts.splice(index, 1); - return QR.status(); + QR.status(); + return typeof (base = QR.captcha).updateThread === "function" ? base.updateThread() : void 0; }; _Class.prototype["delete"] = function() { @@ -25928,7 +26057,7 @@ QR = (function() { }; _Class.prototype.save = function(input, forced) { - var name, prev; + var base, name, prev; if (input.type === 'checkbox') { this.spoiler = input.checked; return; @@ -25943,6 +26072,9 @@ QR = (function() { case 'thread': (this.thread !== 'new' ? $.addClass : $.rmClass)(QR.nodes.el, 'reply-to-thread'); QR.status(); + if (typeof (base = QR.captcha).updateThread === "function") { + base.updateThread(); + } break; case 'com': this.updateComment(); @@ -26003,7 +26135,9 @@ QR = (function() { } this.nodes.span.textContent = this.com; QR.captcha.moreNeeded(); - return Captcha.cache.prerequest(); + if (QR.captcha === Captcha.v2) { + return Captcha.cache.prerequest(); + } }; _Class.prototype.isOnlyQuotes = function() { @@ -26335,7 +26469,7 @@ QR = (function() { }; _Class.prototype.drop = function() { - var el, index, newIndex, oldIndex, post; + var base, el, index, newIndex, oldIndex, post; $.rmClass(this, 'over'); if (!this.draggable) { return; @@ -26352,7 +26486,8 @@ QR = (function() { (oldIndex < newIndex ? $.after : $.before)(this, el); post = QR.posts.splice(oldIndex, 1)[0]; QR.posts.splice(newIndex, 0, post); - return QR.status(); + QR.status(); + return typeof (base = QR.captcha).updateThread === "function" ? base.updateThread() : void 0; }; return _Class; diff --git a/builds/4chan-X.zip b/builds/4chan-X.zip index f908ce4c6..ecf1fed6f 100644 Binary files a/builds/4chan-X.zip and b/builds/4chan-X.zip differ diff --git a/builds/updates-beta.json b/builds/updates-beta.json index fbf5149d4..a89702610 100644 --- a/builds/updates-beta.json +++ b/builds/updates-beta.json @@ -3,7 +3,7 @@ "4chan-x@4chan-x.net": { "updates": [ { - "version": "1.14.21.3", + "version": "1.14.21.5", "update_link": "https://www.4chan-x.net/builds/4chan-X-beta.crx" } ] diff --git a/builds/updates-beta.xml b/builds/updates-beta.xml index 513cc85d0..3c1389d81 100644 --- a/builds/updates-beta.xml +++ b/builds/updates-beta.xml @@ -1,7 +1,7 @@ - + diff --git a/builds/updates.json b/builds/updates.json index 75215e77d..44c6733e6 100644 --- a/builds/updates.json +++ b/builds/updates.json @@ -3,7 +3,7 @@ "4chan-x@4chan-x.net": { "updates": [ { - "version": "1.14.21.3", + "version": "1.14.21.5", "update_link": "https://www.4chan-x.net/builds/4chan-X.crx" } ] diff --git a/builds/updates.xml b/builds/updates.xml index 1117a6594..d54173130 100644 --- a/builds/updates.xml +++ b/builds/updates.xml @@ -1,7 +1,7 @@ - + diff --git a/src/Posting/Captcha.t.coffee b/src/Posting/Captcha.t.coffee new file mode 100644 index 000000000..954b23fd7 --- /dev/null +++ b/src/Posting/Captcha.t.coffee @@ -0,0 +1,72 @@ +Captcha.t = + init: -> + return if d.cookie.indexOf('pass_enabled=1') >= 0 + return if not (@isEnabled = !!$('#t-root') or !$.id('postForm')) + + root = $.el 'div', className: 'captcha-root' + @nodes = {root} + + $.addClass QR.nodes.el, 'has-captcha', 'captcha-t' + $.after QR.nodes.com.parentNode, root + + moreNeeded: -> + return + + getThread: -> + boardID = g.BOARD.ID + if QR.posts[0].thread is 'new' + threadID = '0' + else + threadID = '' + QR.posts[0].thread + {boardID, threadID} + + setup: (focus) -> + return unless @isEnabled + + if !@nodes.container + @nodes.container = $.el 'div', className: 'captcha-container' + $.prepend @nodes.root, @nodes.container + Captcha.t.currentThread = Captcha.t.getThread() + $.global -> + el = document.querySelector '#qr .captcha-container' + window.TCaptcha.init el, @boardID, +@threadID + window.TCaptcha.setErrorCb (err) -> + window.dispatchEvent new CustomEvent('CreateNotification', {detail: { + type: 'warning', + content: '' + err + }}) + , Captcha.t.currentThread + + if focus + $('#t-resp').focus() + + destroy: -> + return unless @isEnabled and @nodes.container + $.global -> + window.TCaptcha.destroy() + $.rm @nodes.container + delete @nodes.container + + updateThread: -> + {boardID, threadID} = Captcha.t.currentThread + newThread = Captcha.t.getThread() + unless newThread.boardID is boardID and newThread.threadID is threadID + Captcha.t.destroy() + Captcha.t.setup() + + getOne: -> + response = {} + if @nodes.container + for key in ['t-response', 't-challenge'] + response[key] = $("[name='#{key}']", @nodes.container).value + if !response['t-response'] + response = null + response + + setUsed: -> + if @nodes.container + $.global -> + window.TCaptcha.clearChallenge() + + occupied: -> + !!@nodes.container diff --git a/src/Posting/QR.coffee b/src/Posting/QR.coffee index fa50ceee0..0b5ee1c0d 100644 --- a/src/Posting/QR.coffee +++ b/src/Posting/QR.coffee @@ -26,8 +26,6 @@ QR = @posts = [] - @captcha = Captcha.v2 - $.on d, '4chanXInitFinished', -> BoardConfig.ready QR.initReady Callbacks.Post.push @@ -50,6 +48,8 @@ QR = Header.addShortcut 'qr', sc, 540 initReady: -> + captchaVersion = if $('#t-root') then 't' else 'v2' + QR.captcha = Captcha[captchaVersion] QR.postingIsEnabled = true {config} = g.BOARD @@ -684,8 +684,10 @@ QR = if g.BOARD.ID is 'r9k' and !post.com?.match(/[a-z-]/i) err or= 'Original comment required.' - if QR.captcha.isEnabled and !(/\b_ct=/.test(d.cookie) and threadID) and !(err and !force) - captcha = QR.captcha.getOne(!!threadID) or Captcha.cache.request(!!threadID) + if QR.captcha.isEnabled and !(QR.captcha is Captcha.v2 and /\b_ct=/.test(d.cookie) and threadID) and !(err and !force) + captcha = QR.captcha.getOne(!!threadID) + if QR.captcha is Captcha.v2 + captcha or= Captcha.cache.request(!!threadID) unless captcha err = 'No valid captcha.' QR.captcha.setup(!QR.cooldown.auto or d.activeElement is QR.nodes.status) @@ -736,11 +738,15 @@ QR = cb = (response) -> if response? QR.currentCaptcha = response - if response.challenge? - options.form.append 'recaptcha_challenge_field', response.challenge - options.form.append 'recaptcha_response_field', response.response + if QR.captcha is Captcha.v2 + if response.challenge? + options.form.append 'recaptcha_challenge_field', response.challenge + options.form.append 'recaptcha_response_field', response.response + else + options.form.append 'g-recaptcha-response', response.response else - options.form.append 'g-recaptcha-response', response.response + for key, val of response + options.form.append key, val QR.req = $.ajax "https://sys.#{location.hostname.split('.')[1]}.org/#{g.BOARD}/post", options QR.req.progress = '...' @@ -749,10 +755,11 @@ QR = QR.req = progress: '...' abort: -> - Captcha.cache.abort() + if QR.captcha is Captcha.v2 + Captcha.cache.abort() cb = null captcha (response) -> - if Captcha.cache.haveCookie() + if QR.captcha is Captcha.v2 and Captcha.cache.haveCookie() cb?() Captcha.cache.save response if response else if response @@ -780,10 +787,11 @@ QR = $('a', err)?.target = '_blank' # duplicate image link else if (connErr = (!@response or @response.title isnt 'Post successful!')) err = QR.connectionError() - Captcha.cache.save QR.currentCaptcha if QR.currentCaptcha + Captcha.cache.save QR.currentCaptcha if QR.captcha is Captcha.v2 and QR.currentCaptcha else if @status isnt 200 err = "Error #{@statusText} (#{@status})" + QR.captcha.setUsed?() unless connErr delete QR.currentCaptcha if err @@ -901,7 +909,7 @@ QR = if (oldReq = QR.req) and !QR.req.isUploadFinished delete QR.req oldReq.abort() - Captcha.cache.save QR.currentCaptcha if QR.currentCaptcha + Captcha.cache.save QR.currentCaptcha if QR.captcha is Captcha.v2 and QR.currentCaptcha delete QR.currentCaptcha QR.posts[0].unlock() QR.cooldown.auto = false diff --git a/src/Posting/QR.post.coffee b/src/Posting/QR.post.coffee index c0b376be2..a658a82a2 100644 --- a/src/Posting/QR.post.coffee +++ b/src/Posting/QR.post.coffee @@ -74,6 +74,7 @@ QR.post = class (QR.posts[index-1] or QR.posts[index+1]).select() QR.posts.splice index, 1 QR.status() + QR.captcha.updateThread?() delete: -> $.rm @nodes.el @@ -129,6 +130,7 @@ QR.post = class when 'thread' (if @thread isnt 'new' then $.addClass else $.rmClass) QR.nodes.el, 'reply-to-thread' QR.status() + QR.captcha.updateThread?() when 'com' @updateComment() when 'filename' @@ -167,7 +169,8 @@ QR.post = class QR.characterCount() @nodes.span.textContent = @com QR.captcha.moreNeeded() - Captcha.cache.prerequest() + if QR.captcha is Captcha.v2 + Captcha.cache.prerequest() isOnlyQuotes: -> (@com or '').trim() is (@quotedText or '').trim() @@ -402,3 +405,4 @@ QR.post = class post = QR.posts.splice(oldIndex, 1)[0] QR.posts.splice newIndex, 0, post QR.status() + QR.captcha.updateThread?() diff --git a/version.json b/version.json index 2867a2ecf..0a7374711 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { - "version": "1.14.21.3", - "date": "2021-05-07T07:49:08.122Z" + "version": "1.14.21.5", + "date": "2021-07-07T06:16:45.892Z" } \ No newline at end of file