Merge commit '68dbb73' into noscript; allow selection of noscript or Javascript captcha.

Similar to reverted merge commit c7433d9271717df3f0f8d64e22abf73e85f8a5ca.

Conflicts:
	src/Posting/QR.captcha.coffee
	src/Posting/QR.coffee
This commit is contained in:
ccd0 2014-12-12 17:59:14 -08:00
commit 76507b6a34
25 changed files with 858 additions and 611 deletions

View File

@ -3,6 +3,49 @@ The attributions below are for work that has been incorporated into the script a
The links to individual versions below are to copies of the script with the update URL removed. If you want automatic updates, install the script from the links on the [main page](https://github.com/ccd0/4chan-x).
<!-- v1.9.15.x -->
### v1.9.15.10
*2014-12-09* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.10/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.10/builds/4chan-X-noupdate.crx "Chromium version")]
**ccd0**
- Add `Post on Captcha Completion` option (default: off) to post when the captcha is completed rather than just focusing on the submit button.
### v1.9.15.9
*2014-12-09* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.9/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.9/builds/4chan-X-noupdate.crx "Chromium version")]
**ccd0**
- Merge v1.9.14.9: Fix bug causing `Auto-load captcha` to not work when using `Persistent QR`.
### v1.9.15.8
*2014-12-09* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.8/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.8/builds/4chan-X-noupdate.crx "Chromium version")]
**ccd0**
- Merge v1.9.14.8: Fix bug that may be causing captchas entered to be ignored sometimes.
### v1.9.15.7
*2014-12-09* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.7/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.7/builds/4chan-X-noupdate.crx "Chromium version")]
Merge v1.9.14.7:
**ccd0**
- Fix more captcha bugs.
- No longer open the original post form automatically when `Hide Original Post Form` is unchecked, as it interferes with the original form's captcha loading.
### v1.9.15.6
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.6/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.6/builds/4chan-X-noupdate.crx "Chromium version")]
Merge v1.9.14.6:
**ccd0**
- Fix some captcha bugs.
- The QR now focuses on the submit button after captcha completion, unless you are dumping and more captchas are needed.
- Fix updater bugs introduced in v1.9.14.0.
### v1.9.15.5
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.5/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.5/builds/4chan-X-noupdate.crx "Chromium version")]
**ccd0**
- Update 4chan X for Recaptcha v2 (as in v1.9.14.5).
### v1.9.15.4
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.4/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.15.4/builds/4chan-X-noupdate.crx "Chromium version")]
@ -42,6 +85,39 @@ Based on v1.9.14.2.
- Bug fixes.
<!-- v1.9.14.x -->
### v1.9.14.9
*2014-12-09* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.9/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.9/builds/4chan-X-noupdate.crx "Chromium version")]
**ccd0**
- Fix bug causing `Auto-load captcha` to not work when using `Persistent QR`.
### v1.9.14.8
*2014-12-09* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.8/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.8/builds/4chan-X-noupdate.crx "Chromium version")]
**ccd0**
- Fix bug that may be causing captchas entered to be ignored sometimes.
### v1.9.14.7
*2014-12-09* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.7/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.7/builds/4chan-X-noupdate.crx "Chromium version")]
**ccd0**
- Fix more captcha bugs.
- No longer open the original post form automatically when `Hide Original Post Form` is unchecked, as it interferes with the original form's captcha loading.
### v1.9.14.6
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.6/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.6/builds/4chan-X-noupdate.crx "Chromium version")]
**ccd0**
- Fix some captcha bugs.
- The QR now focuses on the submit button after captcha completion, unless you are dumping and more captchas are needed.
- Fix updater bugs introduced in v1.9.14.0.
### v1.9.14.5
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.5/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.5/builds/4chan-X-noupdate.crx "Chromium version")]
**ccd0**
- Update 4chan X for Recaptcha v2.
### v1.9.14.4
*2014-12-08* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.4/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.14.4/builds/4chan-X-noupdate.crx "Chromium version")]

View File

@ -61,6 +61,7 @@ module.exports = (grunt) ->
'src/Filtering/**/*.coffee'
'src/Quotelinks/**/*.coffee'
'src/Posting/QR.coffee'
'src/Posting/Captcha.coffee'
'src/Posting/**/*.coffee'
'src/Images/**/*.coffee'
'src/Linkification/**/*.coffee'

View File

@ -1,5 +1,5 @@
/*
* 4chan X - Version 1.9.15.4
* 4chan X - Version 1.9.15.10
*
* Licensed under the MIT license.
* https://github.com/ccd0/4chan-x/blob/master/LICENSE

Binary file not shown.

View File

@ -1,6 +1,6 @@
// ==UserScript==
// @name 4chan X beta
// @version 1.9.15.4
// @version 1.9.15.10
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -1,6 +1,6 @@
// ==UserScript==
// @name 4chan X
// @version 1.9.15.4
// @version 1.9.15.10
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx' version='1.9.15.4' />
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx' version='1.9.15.10' />
</app>
</gupdate>

View File

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X.crx' version='1.9.15.4' />
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X.crx' version='1.9.15.10' />
</app>
</gupdate>

View File

@ -3,7 +3,7 @@
"description": "Cross-browser userscript for maximum lurking on 4chan.",
"meta": {
"name": "4chan X",
"version": "1.9.15.4",
"version": "1.9.15.10",
"repo": "https://github.com/ccd0/4chan-x/",
"page": "https://github.com/ccd0/4chan-x",
"downloads": "https://ccd0.github.io/4chan-x/builds/",

View File

@ -371,13 +371,21 @@ Config =
true
'Show notifications on successful post creation or file uploading.'
]
'Force Noscript Captcha': [
false
'Use the non-Javascript fallback captcha in the QR even if Javascript is enabled.'
]
'Captcha Warning Notifications': [
true
'When disabled, shows a red border on the CAPTCHA input until a key is pressed instead of a notification.'
]
'Auto-load captcha': [
false
'Automatically load the captcha when you open a thread, and reload it after you post.'
'Automatically load the captcha in the QR even if your post is empty.'
]
'Post on Captcha Completion': [
false
'Submit the post immediately when the captcha is completed.'
]
'Bottom QR Link': [
true

View File

@ -1,7 +1,7 @@
Main =
init: ->
if location.hostname is 'www.google.com'
return $.ready -> QR.captcha.initFrame()
return $.ready -> Captcha.noscript.initFrame()
g.threads = new SimpleDict
g.posts = new SimpleDict

View File

@ -960,8 +960,7 @@ span.hide-announcement {
/* QR */
:root.hide-original-post-form #togglePostFormLink,
:root:not(.catalog) #togglePostFormLink,
#qr.autohide:not(.focus):not(:hover):not(:active) > form,
#qr.autohide:not(.focus):not(:hover):not(:active):not(.captcha-open) > form,
:root.thread-view #qr:not(.show-new-thread-option) select[data-name="thread"],
#file-n-submit:not(.has-file) #qr-filerm {
display: none;
@ -969,9 +968,6 @@ span.hide-announcement {
:root.hide-original-post-form #postForm {
display: none !important;
}
:root:not(.hide-original-post-form):not(.catalog) #postForm {
display: table;
}
#qr select,
#dump-button,
#url-button,
@ -1069,6 +1065,7 @@ input.field.tripped:not(:hover):not(:focus) {
#qr textarea {
resize: both;
}
/* Noscript Recaptcha */
.captcha-img {
margin: 0px;
text-align: center;
@ -1087,6 +1084,30 @@ input.field.tripped:not(:hover):not(:focus) {
#qr-captcha-iframe {
display: none;
}
/* Recaptcha v2 */
#qr .captcha-root {
position: relative;
}
#qr .captcha-container > div > div {
margin: auto;
}
#qr .captcha-counter {
display: block;
width: 100%;
text-align: center;
pointer-events: none;
}
#qr.captcha-open .captcha-counter {
position: absolute;
bottom: 3px;
}
#qr .captcha-counter > a {
pointer-events: auto;
}
#qr:not(.captcha-open) .captcha-counter > a {
display: block;
width: 100%;
}
.field {
-moz-box-sizing: border-box;
margin: 0px;

View File

@ -132,7 +132,7 @@ Keybinds =
when Conf['Open catalog']
window.location = CatalogLinks.catalog()
when Conf['Cycle sort type']
return unless Conf['JSON Navigation']
return unless Conf['JSON Navigation'] and g.VIEW is 'index' and g.BOARD isnt 'f'
Index.cycleSortType()
# Thread Navigation
when Conf['Next thread']

View File

@ -320,6 +320,7 @@ ThreadUpdater =
ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25
for post in posts
root = post.nodes.root
unless QuoteThreading.insert post
$.add ThreadUpdater.root, post.nodes.root
$.event 'PostsInserted'

View File

@ -0,0 +1 @@
Captcha = {}

View File

@ -1,4 +1,4 @@
QR.captcha =
Captcha.noscript =
lifetime: 120 * $.SECOND
iframeURL: '//www.google.com/recaptcha/api/fallback?k=<%= meta.recaptchaKey %>'

View File

@ -0,0 +1,167 @@
Captcha.v2 =
init: ->
return if d.cookie.indexOf('pass_enabled=1') >= 0
return unless @isEnabled = !!$.id 'g-recaptcha'
@captchas = []
$.get 'captchas', [], ({captchas}) ->
QR.captcha.sync captchas
$.sync 'captchas', @sync.bind @
root = $.el 'div', className: 'captcha-root'
$.extend root, <%= html(
'<div class="captcha-counter"><a href="javascript:;"></a></div>'
) %>
counter = $ '.captcha-counter > a', root
@nodes = {root, counter}
@count()
$.addClass QR.nodes.el, 'has-captcha'
$.after QR.nodes.com.parentNode, root
$.on counter, 'click', @toggle.bind @
$.on window, 'captcha:success', => @save false
shouldFocus: false
timeouts: {}
postsCount: 0
needed: ->
captchaCount = @captchas.length
captchaCount++ if @nodes.container and !@timeouts.destroy
@postsCount = QR.posts.length
@postsCount = 0 if @postsCount is 1 and !Conf['Auto-load captcha'] and !QR.posts[0].com and !QR.posts[0].file
captchaCount < @postsCount
onPostChange: ->
@setup() if @postsCount is 0
toggle: ->
if @nodes.container and !@timeouts.destroy
@destroy()
else
@setup true, true
setup: (focus, force) ->
return unless @isEnabled and (@needed() or force)
$.addClass QR.nodes.el, 'captcha-open'
@shouldFocus = true if focus
if @timeouts.destroy
clearTimeout @timeouts.destroy
delete @timeouts.destroy
return @reload()
return if @nodes.container
@nodes.container = $.el 'div', className: 'captcha-container'
$.prepend @nodes.root, @nodes.container
new MutationObserver(@afterSetup.bind @).observe @nodes.container,
childList: true
subtree: true
$.globalEval '''
(function() {
function render() {
var container = document.querySelector("#qr .captcha-container");
container.dataset.widgetID = window.grecaptcha.render(container, {
sitekey: '<%= meta.recaptchaKey %>',
theme: document.documentElement.classList.contains('tomorrow') ? 'dark' : 'light',
callback: function(response) {
window.dispatchEvent(new CustomEvent("captcha:success", {detail: response}));
}
});
}
if (window.grecaptcha) {
render();
} else {
var cbNative = window.onRecaptchaLoaded;
window.onRecaptchaLoaded = function() {
render();
cbNative();
}
}
})();
'''
afterSetup: (mutations) ->
for mutation in mutations
for node in mutation.addedNodes
@setupIFrame node if node.nodeName is 'IFRAME'
@setupTextArea node if node.nodeName is 'TEXTAREA'
return
setupIFrame: (iframe) ->
@setupTime = Date.now()
if QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight
QR.nodes.el.style.top = null
QR.nodes.el.style.bottom = '0px'
iframe.focus() if @shouldFocus
@shouldFocus = false
setupTextArea: (textarea) ->
$.one textarea, 'input', => @save true
destroy: ->
return unless @isEnabled
delete @timeouts.destroy
$.rmClass QR.nodes.el, 'captcha-open'
$.rm @nodes.container if @nodes.container
delete @nodes.container
sync: (captchas=[]) ->
@captchas = captchas
@clear()
@count()
getOne: ->
@clear()
if captcha = @captchas.shift()
@count()
$.set 'captchas', @captchas
captcha.response
else
null
save: (pasted) ->
reload = QR.cooldown.auto and @needed()
$.forceSync 'captchas'
@captchas.push
response: $('textarea', @nodes.container).value
timeout: (if pasted then @setupTime else Date.now()) + 2 * $.MINUTE
@count()
$.set 'captchas', @captchas
if reload
@shouldFocus = true
return @reload()
if pasted
@destroy()
else
@timeouts.destroy ?= setTimeout @destroy.bind(@), 3 * $.SECOND
QR.nodes.status.focus()
QR.submit() if Conf['Post on Captcha Completion']
clear: ->
return unless @captchas.length
now = Date.now()
for captcha, i in @captchas
break if captcha.timeout > now
return unless i
@captchas = @captchas[i..]
@count()
$.set 'captchas', @captchas
@setup true
count: ->
@nodes.counter.textContent = "Captchas: #{@captchas.length}"
clearTimeout @timeouts.clear
if @captchas.length
@timeouts.clear = setTimeout @clear.bind(@), @captchas[0].timeout - Date.now()
reload: (focus) ->
$.globalEval '''
(function() {
var container = document.querySelector("#qr .captcha-container");
window.grecaptcha.reset(container.dataset.widgetID);
})();
'''

View File

@ -7,6 +7,8 @@ QR =
@db = new DataBoard 'yourPosts'
@posts = []
@captcha = Captcha[if Conf['Force Noscript Captcha'] then 'noscript' else 'v2']
if Conf['QR Shortcut']
sc = $.el 'a',
className: "qr-shortcut fa fa-comment-o #{unless Conf['Persistent QR'] then 'disabled' else ''}"
@ -95,6 +97,7 @@ QR =
if QR.nodes
QR.nodes.el.hidden = false
QR.unhide()
QR.captcha.setup() unless QR.captcha is Captcha.noscript
return
try
QR.dialog()
@ -111,7 +114,7 @@ QR =
QR.cleanNotifications()
d.activeElement.blur()
$.rmClass QR.nodes.el, 'dump'
unless Conf['Captcha Warning Notifications']
if QR.captcha is Captcha.noscript and !Conf['Captcha Warning Notifications']
$.rmClass QR.captcha.nodes.input, 'error' if QR.captcha.isEnabled
if Conf['QR Shortcut']
$.toggleClass $('.qr-shortcut'), 'disabled'
@ -120,7 +123,7 @@ QR =
post.delete()
QR.cooldown.auto = false
QR.status()
if QR.captcha.isEnabled and not Conf['Auto-load captcha']
if QR.captcha isnt Captcha.noscript or (QR.captcha.isEnabled and not Conf['Auto-load captcha'])
QR.captcha.destroy()
focusin: ->
$.addClass QR.nodes.el, 'focus'
@ -146,7 +149,8 @@ QR =
else
el = err
el.removeAttribute 'style'
if QR.captcha.isEnabled and /captcha|verification/i.test el.textContent
captchaErr = QR.captcha.isEnabled and /captcha|verification/i.test el.textContent
if captchaErr and QR.captcha is Captcha.noscript
if QR.captcha.captchas.length is 0
# Focus the captcha input on captcha error.
QR.captcha.nodes.input.focus()
@ -158,6 +162,7 @@ QR =
$.on QR.captcha.nodes.input, 'keydown', ->
$.rmClass QR.captcha.nodes.input, 'error'
else
QR.captcha.setup true if captchaErr and QR.captcha isnt Captcha.noscript
QR.notify el
alert el.textContent if d.hidden
@ -561,6 +566,7 @@ QR =
QR.cooldown.init()
QR.captcha.init()
$.add d.body, dialog
QR.captcha.setup() unless QR.captcha is Captcha.noscript
# Create a custom event when the QR dialog is first initialized.
# Use it to extend the QR's functionalities, or for XTRM RICE.
@ -831,7 +837,7 @@ QR =
icon: Favicon.logo
notif.onclick = ->
QR.open()
QR.captcha.nodes.input.focus()
QR.captcha.nodes.input.focus() if QR.captcha is Captcha.noscript
window.focus()
notif.onshow = ->
setTimeout ->
@ -841,9 +847,10 @@ QR =
unless Conf['Persistent QR'] or postsCount
QR.close()
else
if QR.posts.length > 1 and QR.captcha.isEnabled and QR.captcha.captchas.length is 0
if QR.captcha is Captcha.noscript and QR.posts.length > 1 and QR.captcha.isEnabled and QR.captcha.captchas.length is 0
QR.captcha.setup()
post.rm()
QR.captcha.setup true unless QR.captcha is Captcha.noscript
QR.cooldown.add req.uploadEndTime, threadID, postID

View File

@ -69,6 +69,8 @@ QR.post = class
@load() if QR.selected is @ # load persona
@select() if select
@unlock()
# Post count temporarily off by 1 when called from QR.post.rm
$.queueTask -> QR.captcha.setup() unless QR.captcha is Captcha.noscript
rm: ->
@delete()
@ -131,6 +133,7 @@ QR.post = class
QR.status()
when 'com'
@nodes.span.textContent = @com
QR.captcha.onPostChange() unless QR.captcha is Captcha.noscript
QR.characterCount()
# Disable auto-posting if you're typing in the first post
# during the last 5 seconds of the cooldown.
@ -159,6 +162,7 @@ QR.post = class
@filename = file.name
@filesize = $.bytesToString file.size
@nodes.label.hidden = false if QR.spoiler
QR.captcha.onPostChange() unless QR.captcha is Captcha.noscript
URL.revokeObjectURL @URL
if @ is QR.selected
@showFileData()