New: Support for indexers with image CAPTCHAs

This commit is contained in:
ta264
2021-03-17 21:30:11 +00:00
committed by Qstick
parent 95d5e0d347
commit 0fa526a1af
15 changed files with 314 additions and 159 deletions

View File

@@ -0,0 +1,84 @@
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import Icon from 'Components/Icon';
import { icons } from 'Helpers/Props';
import FormInputButton from './FormInputButton';
import TextInput from './TextInput';
import styles from './CaptchaInput.css';
function CardigannCaptchaInput(props) {
const {
className,
name,
value,
hasError,
hasWarning,
type,
refreshing,
contentType,
imageData,
onChange,
onRefreshPress
} = props;
const img = `data:${contentType};base64,${imageData}`;
return (
<div>
<div className={styles.captchaInputWrapper}>
<TextInput
className={classNames(
className,
styles.hasButton,
hasError && styles.hasError,
hasWarning && styles.hasWarning
)}
name={name}
value={value}
onChange={onChange}
/>
<FormInputButton
onPress={onRefreshPress}
>
<Icon
name={icons.REFRESH}
isSpinning={refreshing}
/>
</FormInputButton>
</div>
{
type === 'image' &&
<div className={styles.recaptchaWrapper}>
<img
src={img}
/>
</div>
}
</div>
);
}
CardigannCaptchaInput.propTypes = {
className: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
hasError: PropTypes.bool,
hasWarning: PropTypes.bool,
type: PropTypes.string,
refreshing: PropTypes.bool.isRequired,
contentType: PropTypes.string.isRequired,
imageData: PropTypes.string,
onChange: PropTypes.func.isRequired,
onRefreshPress: PropTypes.func.isRequired,
onCaptchaChange: PropTypes.func.isRequired
};
CardigannCaptchaInput.defaultProps = {
className: styles.input,
value: ''
};
export default CardigannCaptchaInput;

View File

@@ -0,0 +1,77 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { getCaptchaCookie, refreshCaptcha, resetCaptcha } from 'Store/Actions/captchaActions';
import CardigannCaptchaInput from './CardigannCaptchaInput';
function createMapStateToProps() {
return createSelector(
(state) => state.captcha,
(captcha) => {
return captcha;
}
);
}
const mapDispatchToProps = {
refreshCaptcha,
getCaptchaCookie,
resetCaptcha
};
class CardigannCaptchaInputConnector extends Component {
//
// Lifecycle
componentDidMount() {
this.onRefreshPress();
}
componentWillUnmount = () => {
this.props.resetCaptcha();
}
//
// Listeners
onRefreshPress = () => {
const {
provider,
providerData,
name,
onChange
} = this.props;
onChange({ name, value: '' });
this.props.resetCaptcha();
this.props.refreshCaptcha({ provider, providerData });
}
//
// Render
render() {
return (
<CardigannCaptchaInput
{...this.props}
onRefreshPress={this.onRefreshPress}
/>
);
}
}
CardigannCaptchaInputConnector.propTypes = {
provider: PropTypes.string.isRequired,
providerData: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
token: PropTypes.string,
onChange: PropTypes.func.isRequired,
refreshCaptcha: PropTypes.func.isRequired,
getCaptchaCookie: PropTypes.func.isRequired,
resetCaptcha: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(CardigannCaptchaInputConnector);

View File

@@ -6,6 +6,7 @@ import translate from 'Utilities/String/translate';
import AutoCompleteInput from './AutoCompleteInput';
import AvailabilitySelectInput from './AvailabilitySelectInput';
import CaptchaInputConnector from './CaptchaInputConnector';
import CardigannCaptchaInputConnector from './CardigannCaptchaInputConnector';
import CheckInput from './CheckInput';
import DeviceInputConnector from './DeviceInputConnector';
import EnhancedSelectInput from './EnhancedSelectInput';
@@ -37,6 +38,9 @@ function getComponent(type) {
case inputTypes.CAPTCHA:
return CaptchaInputConnector;
case inputTypes.CARDIGANNCAPTCHA:
return CardigannCaptchaInputConnector;
case inputTypes.CHECK:
return CheckInput;

View File

@@ -10,6 +10,8 @@ function getType({ type, selectOptionsProviderAction }) {
switch (type) {
case 'captcha':
return inputTypes.CAPTCHA;
case 'cardigannCaptcha':
return inputTypes.CARDIGANNCAPTCHA;
case 'checkbox':
return inputTypes.CHECK;
case 'device':

View File

@@ -1,6 +1,7 @@
export const AUTO_COMPLETE = 'autoComplete';
export const AVAILABILITY_SELECT = 'availabilitySelect';
export const CAPTCHA = 'captcha';
export const CARDIGANNCAPTCHA = 'cardigannCaptcha';
export const CHECK = 'check';
export const DEVICE = 'device';
export const INFO = 'info';
@@ -21,6 +22,7 @@ export const all = [
AUTO_COMPLETE,
AVAILABILITY_SELECT,
CAPTCHA,
CARDIGANNCAPTCHA,
CHECK,
DEVICE,
INFO,

View File

@@ -20,7 +20,10 @@ export const defaultState = {
secretToken: null,
ray: null,
stoken: null,
responseUrl: null
responseUrl: null,
type: null,
contentType: null,
imageData: null
};
//