168 lines
5.1 KiB
CoffeeScript
168 lines
5.1 KiB
CoffeeScript
Captcha.fixes =
|
|
imageKeys: '789456123uiojklm'.split('').concat(['Comma', 'Period'])
|
|
imageKeys16: '7890uiopjkl'.split('').concat(['Semicolon', 'm', 'Comma', 'Period', 'Slash'])
|
|
|
|
css: '''
|
|
.rc-imageselect-target > div:focus, .rc-image-tile-target:focus {
|
|
outline: 2px solid #4a90e2;
|
|
}
|
|
.rc-imageselect-target td:focus {
|
|
box-shadow: inset 0 0 0 2px #4a90e2;
|
|
outline: none;
|
|
}
|
|
.rc-button-default:focus {
|
|
box-shadow: inset 0 0 0 2px #0063d6;
|
|
}
|
|
'''
|
|
|
|
cssNoscript: '''
|
|
.fbc-payload-imageselect {
|
|
position: relative;
|
|
}
|
|
.fbc-payload-imageselect > label {
|
|
position: absolute;
|
|
display: block;
|
|
height: 93.3px;
|
|
width: 93.3px;
|
|
}
|
|
label[data-row="0"] {top: 0px;}
|
|
label[data-row="1"] {top: 93.3px;}
|
|
label[data-row="2"] {top: 186.6px;}
|
|
label[data-col="0"] {left: 0px;}
|
|
label[data-col="1"] {left: 93.3px;}
|
|
label[data-col="2"] {left: 186.6px;}
|
|
.fbc-payload-imageselect > input:focus + label {
|
|
outline: 2px solid #4a90e2;
|
|
}
|
|
.fbc-button-verify input:focus {
|
|
box-shadow: inset 0 0 0 2px #0063d6;
|
|
}
|
|
body.focus .fbc {
|
|
box-shadow: inset 0 0 0 2px #4a90e2;
|
|
}
|
|
'''
|
|
|
|
init: ->
|
|
switch location.pathname.split('/')[3]
|
|
when 'anchor' then @initMain()
|
|
when 'frame' then @initPopup()
|
|
when 'fallback' then @initNoscript()
|
|
|
|
initMain: ->
|
|
$.onExists d.body, '#recaptcha-anchor', (checkbox) ->
|
|
focus = ->
|
|
if d.hasFocus() and d.activeElement in [d.documentElement, d.body]
|
|
checkbox.focus()
|
|
focus()
|
|
$.on window, 'focus', ->
|
|
$.queueTask focus
|
|
|
|
# Remove Privacy and Terms links from tab order.
|
|
for a in $$ '.rc-anchor-pt a'
|
|
a.tabIndex = -1
|
|
return
|
|
|
|
initPopup: ->
|
|
$.addStyle @css
|
|
@fixImages()
|
|
new MutationObserver(=> @fixImages()).observe d.body, {childList: true, subtree: true}
|
|
$.on d, 'keydown', @keybinds.bind(@)
|
|
|
|
initNoscript: ->
|
|
@noscript = true
|
|
data = if (token = $('.fbc-verification-token > textarea')?.value) then {token} else {working: true}
|
|
new Connection(window.parent, '*').send data
|
|
d.body.classList.toggle 'focus', d.hasFocus()
|
|
$.on window, 'focus blur', -> d.body.classList.toggle 'focus', d.hasFocus()
|
|
|
|
@images = $$ '.fbc-payload-imageselect > input'
|
|
@width = 3
|
|
return unless @images.length is 9
|
|
|
|
$.addStyle @cssNoscript
|
|
@addLabels()
|
|
$.on d, 'keydown', @keybinds.bind(@)
|
|
$.on $('.fbc-imageselect-challenge > form'), 'submit', @checkForm.bind(@)
|
|
|
|
fixImages: ->
|
|
@images = $$ '.rc-image-tile-target'
|
|
@images = $$ '.rc-imageselect-target > div, .rc-imageselect-target td' unless @images.length
|
|
@width = $$('.rc-imageselect-target tr:first-of-type td').length or Math.round(Math.sqrt @images.length)
|
|
for img in @images
|
|
img.tabIndex = 0
|
|
if @images.length is 9
|
|
@addTooltips @images
|
|
else
|
|
@addTooltips16 @images
|
|
@complaintLinks()
|
|
|
|
complaintLinks: ->
|
|
for errmsg in $$ '.rc-imageselect-incorrect-response, .rc-imageselect-error-select-one, .rc-imageselect-error-select-more, .rc-imageselect-error-dynamic-more'
|
|
unless $ 'a', errmsg
|
|
link = $.el 'a',
|
|
href: 'https://www.4chan-x.net/captchas.html'
|
|
target: '_blank'
|
|
textContent: '[complain]'
|
|
$.add errmsg, [$.tn(' '), link]
|
|
return
|
|
|
|
addLabels: ->
|
|
imageSelect = $ '.fbc-payload-imageselect'
|
|
labels = for checkbox, i in @images
|
|
checkbox.id = "checkbox-#{i}"
|
|
label = $.el 'label',
|
|
htmlFor: checkbox.id
|
|
label.dataset.row = i // 3
|
|
label.dataset.col = i % 3
|
|
$.after checkbox, label
|
|
label
|
|
@addTooltips labels
|
|
|
|
addTooltips: (nodes) ->
|
|
for node, i in nodes
|
|
node.title = "#{@imageKeys[i]} or #{@imageKeys[i+9][0].toUpperCase()}#{@imageKeys[i+9][1..]}"
|
|
return
|
|
|
|
addTooltips16: (nodes) ->
|
|
for key, i in @imageKeys16
|
|
if i % 4 < @width and (node = nodes[nodes.length - (4 - i//4)*@width + (i % 4)])
|
|
node.title = "#{key[0].toUpperCase()}#{key[1..]}"
|
|
return
|
|
|
|
checkForm: (e) ->
|
|
n = 0
|
|
n++ for checkbox in @images when checkbox.checked
|
|
e.preventDefault() if n is 0
|
|
|
|
keybinds: (e) ->
|
|
return unless @images and doc.contains(@images[0])
|
|
n = @images.length
|
|
w = @width
|
|
last = n + w - 1
|
|
|
|
reload = $ '#recaptcha-reload-button, .fbc-button-reload'
|
|
verify = $ '#recaptcha-verify-button, .fbc-button-verify > input'
|
|
x = @images.indexOf d.activeElement
|
|
if x < 0
|
|
x = if d.activeElement is verify then last else n
|
|
key = Keybinds.keyCode e
|
|
|
|
if !@noscript and key is 'Space' and x < n
|
|
@images[x].click()
|
|
else if n is 9 and (i = @imageKeys.indexOf key) >= 0
|
|
@images[i % 9].click()
|
|
verify.focus()
|
|
else if n isnt 9 and (i = @imageKeys16.indexOf key) >= 0 and i % 4 < w and (img = @images[n - (4 - i//4)*w + (i % 4)])
|
|
img.click()
|
|
verify.focus()
|
|
else if dx = {'Up': n, 'Down': w, 'Left': last, 'Right': 1}[key]
|
|
x = (x + dx) % (n + w)
|
|
if n < x < last
|
|
x = if dx is last then n else last
|
|
(@images[x] or (if x is n then reload) or (if x is last then verify)).focus()
|
|
else
|
|
return
|
|
|
|
e.preventDefault()
|
|
e.stopPropagation()
|