@swetrix/captcha 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nvmrc +1 -0
- package/LICENSE +21 -0
- package/README.md +33 -0
- package/dist/assets/logo_blue.png +0 -0
- package/dist/assets/logo_white.png +0 -0
- package/dist/captcha-loader.js +1 -0
- package/dist/captcha.js +1 -0
- package/dist/esnext/captcha-loader.d.ts +33 -0
- package/dist/esnext/captcha-loader.js +182 -0
- package/dist/esnext/captcha-loader.js.map +1 -0
- package/dist/esnext/captcha.d.ts +37 -0
- package/dist/esnext/captcha.js +248 -0
- package/dist/esnext/captcha.js.map +1 -0
- package/dist/pages/dark.html +248 -0
- package/dist/pages/light.html +243 -0
- package/dist/pages/test.html +33 -0
- package/package.json +47 -0
- package/rollup.config.js +52 -0
- package/src/assets/logo_blue.png +0 -0
- package/src/assets/logo_white.png +0 -0
- package/src/captcha-loader.ts +242 -0
- package/src/captcha.ts +284 -0
- package/src/pages/dark.html +248 -0
- package/src/pages/light.html +243 -0
- package/src/pages/test.html +33 -0
- package/tsconfig.esnext.json +17 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
const isDevelopment = window.__SWETRIX_CAPTCHA_DEV || false
|
|
3
|
+
|
|
4
|
+
const CAPTCHA_SELECTOR = '.swecaptcha'
|
|
5
|
+
const LIGHT_CAPTCHA_IFRAME_URL = isDevelopment ? './light.html' : 'https://cap.swetrix.com/pages/light'
|
|
6
|
+
const DARK_CAPTCHA_IFRAME_URL = isDevelopment ? './dark.html' : 'https://cap.swetrix.com/pages/dark'
|
|
7
|
+
const DEFAULT_RESPONSE_INPUT_NAME = 'swetrix-captcha-response'
|
|
8
|
+
const MESSAGE_IDENTIFIER = 'swetrix-captcha'
|
|
9
|
+
const ID_PREFIX = 'swetrix-captcha-'
|
|
10
|
+
const THEMES = ['light', 'dark']
|
|
11
|
+
const PID_REGEX = /^(?!.*--)[a-zA-Z0-9-]{12}$/
|
|
12
|
+
|
|
13
|
+
enum LOG_ACTIONS {
|
|
14
|
+
log = 'log',
|
|
15
|
+
error = 'error',
|
|
16
|
+
warn = 'warn',
|
|
17
|
+
info = 'info',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const DUMMY_PIDS = [
|
|
21
|
+
'AP00000000000', 'MP00000000000', 'FAIL000000000',
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
const isValidPID = (pid: string) => DUMMY_PIDS.includes(pid) || PID_REGEX.test(pid)
|
|
25
|
+
|
|
26
|
+
const FRAME_HEIGHT_MAPPING = {
|
|
27
|
+
default: '66px',
|
|
28
|
+
manual: '200px',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const getFrameID = (cid: string) => `${cid}-frame`
|
|
32
|
+
|
|
33
|
+
const ids: string[] = []
|
|
34
|
+
|
|
35
|
+
const log = (status: LOG_ACTIONS, text: string) => {
|
|
36
|
+
console[status](`[Swetrix Captcha] ${text}`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const appendParamsToURL = (url: string, params: any) => {
|
|
40
|
+
const queryString = Object.keys(params).map((key) => {
|
|
41
|
+
return `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`
|
|
42
|
+
}).join('&')
|
|
43
|
+
|
|
44
|
+
return `${url}?${queryString}`
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const renderCaptcha = (container: Element, params: any) => {
|
|
48
|
+
const cid = generateRandomID()
|
|
49
|
+
const cParams = {
|
|
50
|
+
...params,
|
|
51
|
+
cid, // CAPTCHA ID
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const frame = generateCaptchaFrame(cParams)
|
|
55
|
+
const input = generateHiddenInput(cParams)
|
|
56
|
+
|
|
57
|
+
container.appendChild(frame)
|
|
58
|
+
container.appendChild(input)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const generateRandomID = (): string => {
|
|
62
|
+
const randomID = ID_PREFIX + Math.random().toString(36).substr(2, 6)
|
|
63
|
+
|
|
64
|
+
if (ids.includes(randomID)) {
|
|
65
|
+
return generateRandomID()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
ids.push(randomID)
|
|
69
|
+
|
|
70
|
+
return randomID
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const postMessageCallback = (pmEvent: MessageEvent) => {
|
|
74
|
+
// TODO: Validate origin
|
|
75
|
+
|
|
76
|
+
const { data } = pmEvent
|
|
77
|
+
|
|
78
|
+
if (!data) {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const {
|
|
83
|
+
type, cid, event,
|
|
84
|
+
} = data
|
|
85
|
+
|
|
86
|
+
if (type !== MESSAGE_IDENTIFIER) {
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!cid || !ids.includes(cid)) {
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const input = document.getElementById(cid)
|
|
95
|
+
const inputExists = input !== null
|
|
96
|
+
|
|
97
|
+
switch (event) {
|
|
98
|
+
case 'success': {
|
|
99
|
+
const { token } = data
|
|
100
|
+
|
|
101
|
+
if (!inputExists) {
|
|
102
|
+
log(LOG_ACTIONS.error, '[PM -> success] Input element does not exist.')
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// @ts-ignore
|
|
107
|
+
input.value = token
|
|
108
|
+
|
|
109
|
+
break
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
case 'failure': {
|
|
113
|
+
if (!inputExists) {
|
|
114
|
+
log(LOG_ACTIONS.error, '[PM -> failure] Input element does not exist.')
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// @ts-ignore
|
|
119
|
+
input.value = ''
|
|
120
|
+
|
|
121
|
+
break
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
case 'tokenExpired': {
|
|
125
|
+
if (!inputExists) {
|
|
126
|
+
log(LOG_ACTIONS.error, '[PM -> failure] Input element does not exist.')
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
input.value = ''
|
|
132
|
+
|
|
133
|
+
break
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
case 'manualStarted': {
|
|
137
|
+
const frame = document.getElementById(getFrameID(cid))
|
|
138
|
+
|
|
139
|
+
if (!frame) {
|
|
140
|
+
log(LOG_ACTIONS.error, '[PM -> manualStarted] Frame does not exist.')
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
frame.style.height = FRAME_HEIGHT_MAPPING.manual
|
|
145
|
+
|
|
146
|
+
break
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
case 'manualFinished': {
|
|
150
|
+
const frame = document.getElementById(getFrameID(cid))
|
|
151
|
+
|
|
152
|
+
if (!frame) {
|
|
153
|
+
log(LOG_ACTIONS.error, '[PM -> manualFinished] Frame does not exist.')
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
frame.style.height = FRAME_HEIGHT_MAPPING.default
|
|
158
|
+
|
|
159
|
+
break
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const generateCaptchaFrame = (params: any) => {
|
|
165
|
+
const { theme } = params
|
|
166
|
+
const captchaFrame = document.createElement('iframe')
|
|
167
|
+
|
|
168
|
+
captchaFrame.id = getFrameID(params.cid)
|
|
169
|
+
captchaFrame.src = theme === 'dark'
|
|
170
|
+
? appendParamsToURL(DARK_CAPTCHA_IFRAME_URL, params)
|
|
171
|
+
: appendParamsToURL(LIGHT_CAPTCHA_IFRAME_URL, params)
|
|
172
|
+
captchaFrame.style.height = FRAME_HEIGHT_MAPPING.default
|
|
173
|
+
captchaFrame.title = 'Swetrix Captcha'
|
|
174
|
+
captchaFrame.style.border = 'none'
|
|
175
|
+
captchaFrame.style.width = '302px'
|
|
176
|
+
captchaFrame.style.overflow = 'visible'
|
|
177
|
+
|
|
178
|
+
return captchaFrame
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const generateHiddenInput = (params: any) => {
|
|
182
|
+
const { cid } = params
|
|
183
|
+
const input = document.createElement('input')
|
|
184
|
+
|
|
185
|
+
input.type = 'hidden'
|
|
186
|
+
input.name = params.respName
|
|
187
|
+
input.value = ''
|
|
188
|
+
input.id = cid
|
|
189
|
+
|
|
190
|
+
return input
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const validateParams = (params: any) => {
|
|
194
|
+
const { theme, pid } = params
|
|
195
|
+
|
|
196
|
+
if (theme && !THEMES.includes(theme)) {
|
|
197
|
+
log(LOG_ACTIONS.error, `Invalid data-theme parameter: ${theme}`)
|
|
198
|
+
return false
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (!pid || !isValidPID(pid)) {
|
|
202
|
+
log(LOG_ACTIONS.error, `Invalid data-project-id parameter: ${pid}`)
|
|
203
|
+
return false
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return true
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const parseParams = (container: Element): object => ({
|
|
210
|
+
pid: container.getAttribute('data-project-id'),
|
|
211
|
+
respName: container.getAttribute('data-response-input-name') || DEFAULT_RESPONSE_INPUT_NAME,
|
|
212
|
+
theme: container.getAttribute('data-theme'),
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
const main = (forced = false) => {
|
|
216
|
+
if (!forced && 'swecaptcha' in window) {
|
|
217
|
+
log(LOG_ACTIONS.warn, 'Captcha is already loaded.')
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// TODO: Add some callbacks here
|
|
221
|
+
// @ts-ignore
|
|
222
|
+
window.swecaptcha = true
|
|
223
|
+
window.addEventListener('message', postMessageCallback)
|
|
224
|
+
|
|
225
|
+
const containers = Array.from(document.querySelectorAll(CAPTCHA_SELECTOR))
|
|
226
|
+
|
|
227
|
+
for (const container of containers) {
|
|
228
|
+
const params = parseParams(container)
|
|
229
|
+
|
|
230
|
+
if (!validateParams(params)) {
|
|
231
|
+
log(LOG_ACTIONS.error, 'Aborting captcha rendering due to invalid parameters.')
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
renderCaptcha(container, params)
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// @ts-ignore
|
|
240
|
+
window.swetrixCaptchaForceLoad = () => main(true)
|
|
241
|
+
|
|
242
|
+
document.addEventListener('DOMContentLoaded', () => main())
|
package/src/captcha.ts
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
const isDevelopment = window.__SWETRIX_CAPTCHA_DEV || false
|
|
3
|
+
|
|
4
|
+
const API_URL = isDevelopment ? 'http://localhost:5005/v1/captcha' : 'https://api.swetrix.com/v1/captcha'
|
|
5
|
+
const MSG_IDENTIFIER = 'swetrix-captcha'
|
|
6
|
+
const DEFAULT_THEME = 'light'
|
|
7
|
+
const CAPTCHA_TOKEN_LIFETIME = 300 // seconds (5 minutes).
|
|
8
|
+
let TOKEN = ''
|
|
9
|
+
let HASH = ''
|
|
10
|
+
|
|
11
|
+
const ENDPOINTS = {
|
|
12
|
+
VERIFY: '/verify',
|
|
13
|
+
GENERATE: '/generate',
|
|
14
|
+
VERIFY_MANUAL: '/verify-manual',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
enum IFRAME_MESSAGE_TYPES {
|
|
18
|
+
SUCCESS = 'success',
|
|
19
|
+
FAILURE = 'failure',
|
|
20
|
+
TOKEN_EXPIRED = 'tokenExpired',
|
|
21
|
+
MANUAL_STARTED = 'manualStarted',
|
|
22
|
+
MANUAL_FINISHED = 'manualFinished',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
enum ACTION {
|
|
26
|
+
checkbox = 'checkbox',
|
|
27
|
+
failure = 'failure',
|
|
28
|
+
completed = 'completed',
|
|
29
|
+
loading = 'loading',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let activeAction: ACTION = ACTION.checkbox
|
|
33
|
+
|
|
34
|
+
const sendMessageToLoader = (event: IFRAME_MESSAGE_TYPES, data = {}) => {
|
|
35
|
+
window.parent.postMessage({
|
|
36
|
+
event,
|
|
37
|
+
type: MSG_IDENTIFIER,
|
|
38
|
+
// @ts-ignore
|
|
39
|
+
cid: window.__SWETRIX_CAPTCHA_ID,
|
|
40
|
+
...data,
|
|
41
|
+
}, '*')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Sets the provided action visible and the rest hidden
|
|
46
|
+
* @param {*} action checkbox | failure | completed | loading
|
|
47
|
+
*/
|
|
48
|
+
const activateAction = (action: ACTION) => {
|
|
49
|
+
activeAction = action
|
|
50
|
+
|
|
51
|
+
const statusDefault = document.querySelector('#status-default')
|
|
52
|
+
const statusFailure = document.querySelector('#status-failure')
|
|
53
|
+
|
|
54
|
+
const actions = {
|
|
55
|
+
checkbox: document.querySelector('#checkbox'),
|
|
56
|
+
failure: document.querySelector('#failure'),
|
|
57
|
+
completed: document.querySelector('#completed'),
|
|
58
|
+
loading: document.querySelector('#loading'),
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Apply hidden class to all actions
|
|
62
|
+
actions.checkbox?.classList.add('hidden')
|
|
63
|
+
actions.failure?.classList.add('hidden')
|
|
64
|
+
actions.completed?.classList.add('hidden')
|
|
65
|
+
actions.loading?.classList.add('hidden')
|
|
66
|
+
|
|
67
|
+
// Change the status text
|
|
68
|
+
if (action === 'failure') {
|
|
69
|
+
statusDefault?.classList.add('hidden')
|
|
70
|
+
statusFailure?.classList.remove('hidden')
|
|
71
|
+
} else {
|
|
72
|
+
statusDefault?.classList.remove('hidden')
|
|
73
|
+
statusFailure?.classList.add('hidden')
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Remove hidden class from the provided action
|
|
77
|
+
actions[action]?.classList.remove('hidden')
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const setLifetimeTimeout = () => {
|
|
81
|
+
setTimeout(() => {
|
|
82
|
+
sendMessageToLoader(IFRAME_MESSAGE_TYPES.TOKEN_EXPIRED)
|
|
83
|
+
activateAction(ACTION.checkbox)
|
|
84
|
+
}, CAPTCHA_TOKEN_LIFETIME * 1000)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const enableManualChallenge = (svg: string) => {
|
|
88
|
+
const manualChallenge = document.querySelector('#manual-challenge')
|
|
89
|
+
const svgCaptcha = document.querySelector('#svg-captcha')
|
|
90
|
+
|
|
91
|
+
if (!svgCaptcha) {
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!svg) {
|
|
96
|
+
const error = document.createElement('p')
|
|
97
|
+
error.innerText = 'Error loading captcha'
|
|
98
|
+
error.style.color = '#d6292a'
|
|
99
|
+
svgCaptcha?.appendChild(error)
|
|
100
|
+
} else {
|
|
101
|
+
svgCaptcha.innerHTML = svg
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
sendMessageToLoader(IFRAME_MESSAGE_TYPES.MANUAL_STARTED)
|
|
105
|
+
manualChallenge?.classList.remove('hidden')
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const disableManualChallenge = () => {
|
|
109
|
+
const manualChallenge = document.querySelector('#manual-challenge')
|
|
110
|
+
const svgCaptcha = document.querySelector('#svg-captcha')
|
|
111
|
+
|
|
112
|
+
if (!svgCaptcha) {
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
sendMessageToLoader(IFRAME_MESSAGE_TYPES.MANUAL_FINISHED)
|
|
117
|
+
svgCaptcha.innerHTML = ''
|
|
118
|
+
manualChallenge?.classList.add('hidden')
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const generateCaptcha = async () => {
|
|
122
|
+
try {
|
|
123
|
+
const response = await fetch(`${API_URL}${ENDPOINTS.GENERATE}`, {
|
|
124
|
+
method: 'POST',
|
|
125
|
+
headers: {
|
|
126
|
+
'Content-Type': 'application/json',
|
|
127
|
+
},
|
|
128
|
+
body: JSON.stringify({
|
|
129
|
+
// @ts-ignore
|
|
130
|
+
theme: window.__SWETRIX_CAPTCHA_THEME || DEFAULT_THEME,
|
|
131
|
+
// @ts-ignore
|
|
132
|
+
pid: window.__SWETRIX_PROJECT_ID,
|
|
133
|
+
}),
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
if (!response.ok) {
|
|
137
|
+
throw ''
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const data = await response.json()
|
|
141
|
+
return data
|
|
142
|
+
} catch (e) {
|
|
143
|
+
sendMessageToLoader(IFRAME_MESSAGE_TYPES.FAILURE)
|
|
144
|
+
activateAction(ACTION.failure)
|
|
145
|
+
return {}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const verify = async () => {
|
|
150
|
+
try {
|
|
151
|
+
const response = await fetch(`${API_URL}${ENDPOINTS.VERIFY}`, {
|
|
152
|
+
method: 'POST',
|
|
153
|
+
headers: {
|
|
154
|
+
'Content-Type': 'application/json',
|
|
155
|
+
},
|
|
156
|
+
body: JSON.stringify({
|
|
157
|
+
// @ts-ignore
|
|
158
|
+
pid: window.__SWETRIX_PROJECT_ID,
|
|
159
|
+
}),
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
if (!response.ok) {
|
|
163
|
+
return {}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const data = await response.json()
|
|
167
|
+
return data
|
|
168
|
+
} catch (e) {
|
|
169
|
+
sendMessageToLoader(IFRAME_MESSAGE_TYPES.FAILURE)
|
|
170
|
+
activateAction(ACTION.failure)
|
|
171
|
+
return {}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
176
|
+
const captchaComponent = document.querySelector('#swetrix-captcha')
|
|
177
|
+
const branding = document.querySelector('#branding')
|
|
178
|
+
const svgCaptchaInput = document.querySelector('#svg-captcha-input')
|
|
179
|
+
const manualSubmitBtn = document.querySelector('#manual-submit-btn')
|
|
180
|
+
|
|
181
|
+
branding?.addEventListener('click', (e: Event) => {
|
|
182
|
+
e.stopPropagation()
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
manualSubmitBtn?.addEventListener('click', async (e: Event) => {
|
|
186
|
+
e.stopPropagation()
|
|
187
|
+
|
|
188
|
+
if (!svgCaptchaInput) {
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// @ts-ignore
|
|
193
|
+
const code = svgCaptchaInput.value
|
|
194
|
+
|
|
195
|
+
if (!code) {
|
|
196
|
+
return
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
let response
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
response = await fetch(`${API_URL}${ENDPOINTS.VERIFY_MANUAL}`, {
|
|
203
|
+
method: 'POST',
|
|
204
|
+
body: JSON.stringify({
|
|
205
|
+
hash: HASH,
|
|
206
|
+
code,
|
|
207
|
+
// @ts-ignore
|
|
208
|
+
pid: window.__SWETRIX_PROJECT_ID,
|
|
209
|
+
}),
|
|
210
|
+
headers: {
|
|
211
|
+
'Content-Type': 'application/json',
|
|
212
|
+
},
|
|
213
|
+
})
|
|
214
|
+
} catch (e) {
|
|
215
|
+
disableManualChallenge()
|
|
216
|
+
sendMessageToLoader(IFRAME_MESSAGE_TYPES.FAILURE)
|
|
217
|
+
activateAction(ACTION.failure)
|
|
218
|
+
// @ts-ignore
|
|
219
|
+
svgCaptchaInput.value = ''
|
|
220
|
+
return
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (!response.ok) {
|
|
224
|
+
disableManualChallenge()
|
|
225
|
+
sendMessageToLoader(IFRAME_MESSAGE_TYPES.FAILURE)
|
|
226
|
+
activateAction(ACTION.failure)
|
|
227
|
+
// @ts-ignore
|
|
228
|
+
svgCaptchaInput.value = ''
|
|
229
|
+
return
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const { success, token } = await response.json()
|
|
233
|
+
|
|
234
|
+
if (!success) {
|
|
235
|
+
disableManualChallenge()
|
|
236
|
+
sendMessageToLoader(IFRAME_MESSAGE_TYPES.FAILURE)
|
|
237
|
+
activateAction(ACTION.failure)
|
|
238
|
+
// @ts-ignore
|
|
239
|
+
svgCaptchaInput.value = ''
|
|
240
|
+
return
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// @ts-ignore
|
|
244
|
+
svgCaptchaInput.value = ''
|
|
245
|
+
|
|
246
|
+
sendMessageToLoader(IFRAME_MESSAGE_TYPES.SUCCESS, { token })
|
|
247
|
+
setLifetimeTimeout()
|
|
248
|
+
activateAction(ACTION.completed)
|
|
249
|
+
disableManualChallenge()
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
captchaComponent?.addEventListener('click', async () => {
|
|
253
|
+
if (activeAction === ACTION.loading || activeAction === ACTION.completed) {
|
|
254
|
+
return
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (activeAction === ACTION.failure) {
|
|
258
|
+
activateAction(ACTION.checkbox)
|
|
259
|
+
return
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
activateAction(ACTION.loading)
|
|
263
|
+
|
|
264
|
+
try {
|
|
265
|
+
const { token } = await verify()
|
|
266
|
+
|
|
267
|
+
if (!token) {
|
|
268
|
+
throw ''
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
TOKEN = token
|
|
272
|
+
sendMessageToLoader(IFRAME_MESSAGE_TYPES.SUCCESS, { token })
|
|
273
|
+
setLifetimeTimeout()
|
|
274
|
+
activateAction(ACTION.completed)
|
|
275
|
+
return
|
|
276
|
+
} catch (e) {
|
|
277
|
+
const { data, hash } = await generateCaptcha()
|
|
278
|
+
|
|
279
|
+
HASH = hash
|
|
280
|
+
enableManualChallenge(data)
|
|
281
|
+
return
|
|
282
|
+
}
|
|
283
|
+
})
|
|
284
|
+
})
|