From fc7d1bd62f4f91541c2a6609f4dd516e66771415 Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Thu, 23 Nov 2023 00:10:39 +0600 Subject: [PATCH] The GUI for the Captcha service is ready. --- .gitignore | 7 ++ exmplate/images/refresh.png | Bin 0 -> 355 bytes exmplate/index.html | 12 +++ exmplate/script.js | 189 ++++++++++++++++++++++++++++++++++++ exmplate/style.css | 171 ++++++++++++++++++++++++++++++++ 5 files changed, 379 insertions(+) create mode 100644 .gitignore create mode 100644 exmplate/images/refresh.png create mode 100644 exmplate/index.html create mode 100644 exmplate/script.js create mode 100644 exmplate/style.css diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..776d9dc --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +npm-debug.log +yarn-error.log +.env +/node_modules +/.fleet +/.idea +/.vscode diff --git a/exmplate/images/refresh.png b/exmplate/images/refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..a8eb150a0aff4094c98834d3a1690e19f6963287 GIT binary patch literal 355 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2?- zG7x6;t5)LxG9*h}BT9nv(@M${i&7cN%ggmL^RkPR6AM!H@{7`Ezq647Dth4Q;uvDl zyY%u#FK0uMV;|#_MN2Pk{J}Tv(UQpz6q + + + + + Title + + +
+ + + \ No newline at end of file diff --git a/exmplate/script.js b/exmplate/script.js new file mode 100644 index 0000000..67c7f88 --- /dev/null +++ b/exmplate/script.js @@ -0,0 +1,189 @@ +(function (document) { + const captchaBlocks = document.querySelectorAll('div.captcha-service-kor-elf'); + captchaBlocks.forEach(function (element) { + const shadow = element.attachShadow({ mode: 'closed' }); + const button = document.createElement("button"); + const style = document.createElement('link'); + const domain = element.getAttribute('data-domain'); + const token = element.getAttribute('data-token'); + + let windowCaptcha = null; + + style.rel = 'stylesheet'; + style.type = 'text/css'; + style.href = 'style.css'; + shadow.appendChild(style); + + button.textContent = 'Я не робот!'; + button.type = 'button'; + button.classList.add('button-open-window-captcha'); + shadow.appendChild(button); + button.addEventListener('click', function () { + if (windowCaptcha === null) { + windowCaptcha = createWindowCaptcha(shadow, domain, token); + } + windowCaptcha.style.display = 'block'; + actionGetCaptcha(windowCaptcha, domain, token, shadow); + }); + }); + + function createWindowCaptcha (shadow, domain, token) { + const windowCaptcha = document.createElement('div'); + windowCaptcha.classList.add('window-captcha'); + windowCaptcha.innerHTML = `
+
Я не робот!
+
+
`; + shadow.appendChild(windowCaptcha); + + windowCaptcha.addEventListener('click', function (event) { + if (event.target !== windowCaptcha) { + return null; + } + actionClose(windowCaptcha); + }); + + windowCaptcha.querySelector('button.window-captcha__close').addEventListener('click', function () { + actionClose(windowCaptcha); + }); + + windowCaptcha.querySelector('button.window-captcha__reload').addEventListener('click', function () { + actionGetCaptcha(windowCaptcha, domain, token); + }); + + return windowCaptcha; + } + + function actionClose(windowCaptcha) + { + windowCaptcha.style.display = 'none'; + } + + function actionGetCaptcha(windowCaptcha, domain, token, shadow) + { + let bodyBlock = windowCaptcha.querySelector('div.window-captcha__content__body'); + if (bodyBlock.querySelectorAll('.loading').length > 0) { + return null; + } + bodyBlock.innerHTML = '
'; + fetch(domain + '/api/v1/captcha', { + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'public-token': token + } + }) + .then(response => response.json()) + .then(function (data) { + let originalWidth = data.image_body.width; + let originalHeight = data.image_body.height; + bodyBlock.innerHTML = ` +
+
+

Выберите значение в том порядке, на котором на картинке выше:

+
+ + +
+ `; + let blockCoordinator = bodyBlock.querySelector('div.window-captcha__content__body__coordinator'); + let blockCoordinatorImg = blockCoordinator.querySelector('img'); + blockCoordinatorImg.addEventListener('click', function (event) { + let pointer = document.createElement('div'); + pointer.style.left = ( event.offsetX / blockCoordinatorImg.width * 100 ) + '%'; + pointer.style.top = ( event.offsetY / blockCoordinatorImg.height * 100 ) + '%'; + pointer.classList.add('pointer'); + + let coordinatorX = event.offsetX * (originalWidth / blockCoordinatorImg.width) + let coordinatorY = event.offsetY * (originalHeight / blockCoordinatorImg.height) + + let pointerNumber = blockCoordinator.querySelectorAll('.pointer').length + 1 + pointer.innerHTML = ` + ${ pointerNumber } + + + `; + + pointer.addEventListener('click', function () { + pointer.remove(); + blockCoordinator.querySelectorAll('.pointer').forEach(function (elementPointer, pointIndex) { + elementPointer.querySelector('span.pounter__number').textContent = pointIndex + 1; + }); + }); + + blockCoordinator.appendChild(pointer); + }); + + bodyBlock.querySelector('.window-captcha__content__body__button').addEventListener('click', function () { + checkingCaptcha(bodyBlock, domain, token, shadow); + }); + }) + .catch(error => { + bodyBlock.innerHTML = `
Произошла ошибка, сервис с каптчей не ответил. Попробуйте ещё раз!
`; + }); + } + + function checkingCaptcha (bodyBlock, domain, token, shadow) { + let button = bodyBlock.querySelector('button.window-captcha__content__body__button'); + if (button.querySelectorAll('.loading').length > 0) { + return null; + } + let loadingSpan = document.createElement('span'); + loadingSpan.classList.add('loading'); + button.appendChild(loadingSpan); + + let data = { + captcha_key: bodyBlock.querySelector('.captcha_key').value, + verification: [] + }; + bodyBlock.querySelectorAll('.pointer').forEach(function (elementPointer) { + data["verification"].push({ + x: elementPointer.querySelector('.x').value, + y: elementPointer.querySelector('.y').value + }); + }); + + fetch(domain + '/api/v1/captcha', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'public-token': token + }, + body: JSON.stringify(data) + }) + .then(response => response.json()) + .then(function (data) { + if (typeof data.errors !== 'undefined') { + let errorMessage = ''; + for (let key in data.errors) { + errorMessage += data.errors[key] + '
'; + } + setError(errorMessage, button); + return + } + shadow.querySelector('button.button-open-window-captcha').remove(); + let captchaVerified = document.createElement('div'); + captchaVerified.innerHTML = `Ура!!! Проверку прошли!`; + shadow.appendChild(captchaVerified); + shadow.querySelector('.window-captcha').remove(); + }) + .catch(error => { + setError('Произошла ошибка!', button) + }).finally(function () { + loadingSpan.remove(); + }); + } + + function setError(message, button) { + let errorBlock = document.createElement('div'); + errorBlock.classList.add("error-message"); + errorBlock.innerHTML = message; + button.before(errorBlock); + + setTimeout( function () { + errorBlock.remove(); + }, 3000); + } + +})(document); \ No newline at end of file diff --git a/exmplate/style.css b/exmplate/style.css new file mode 100644 index 0000000..d2328e5 --- /dev/null +++ b/exmplate/style.css @@ -0,0 +1,171 @@ +.captcha-verified { + background: #1D8100; + border: 1px solid #ddd; + border-radius: 90px; + padding: 10px 20px; + color: #000; + font-size: 18px; + font-weight: bold; + font-family: serif; + display: inline-block; + vertical-align: top; +} +.button-open-window-captcha, +.window-captcha__content__body__button { + background: #68AAFF; + border: 1px solid #ddd; + border-radius: 90px; + padding: 10px 20px; + cursor: pointer; + color: #000; + font-size: 18px; + font-weight: bold; + font-family: serif; +} +.button-open-window-captcha:hover, +.window-captcha__content__body__button:hover { + opacity: 0.8; +} +.window-captcha__content__body__button { + border-radius: 0; + width: 100%; + padding: 20px 0; + border: 0; + position: relative; +} +.window-captcha__content__body__button .loading { + background: rgba(255, 255, 255, 0.48); +} +.window-captcha { + background: rgba(0, 0, 0, 0.48); + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + display: none; +} +.window-captcha__close { + background: #961b1b; + position: absolute; + top: 0; + right: 0; + padding: 15px; + font-size: 20px; + font-weight: bold; + font-family: serif; + color: #fff; + border: 0; + cursor: pointer; +} +.window-captcha__close:hover { + opacity: 0.8; +} +.window-captcha__content { + background: #fff; + border-radius: 3px; + margin: 20px auto; + max-width: 600px; + box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.33); +} +.window-captcha__content__header { + position: relative; + font-size: 20px; + font-weight: bold; + color: #000; + font-family: serif; + padding: 14px 40px 7px 20px; + border-bottom: 2px solid #ccc; +} +.window-captcha__reload { + background: url('images/refresh.png') center center no-repeat; + width: 32px; + height: 32px; + border: 1px solid #ddd; + border-radius: 90px; + cursor: pointer; + vertical-align: middle; + margin-left: 10px; +} +.window-captcha__content__reload:hover { + background-color: rgba(0, 0, 0, 0.15); +} +.window-captcha__content__body { + min-height: 400px; + position: relative; +} +.window-captcha__content__body .loading { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; +} +.window-captcha__content__body .loading:before { + width: 40px; + height: 40px; + border: 4px #ddd solid; + border-top: 4px #2e93e6 solid; + border-radius: 50%; + animation: sp-anime 0.8s infinite linear; + display: flex; + justify-content: center; + align-items: center; + content: ' '; +} +.window-captcha__content__body p { + font-size: 20px; + font-weight: bold; + padding: 5px 20px; + font-family: serif; +} +.window-captcha__content__body__coordinator { + cursor: pointer; + position: relative; +} +.window-captcha__content__body__coordinator .pointer { + background: #fff; + position: absolute; + border-radius: 90px; + border: 1px solid #961b1b; + width: 30px; + height: 30px; + margin: -15px 0 0 -15px; + display: flex; + align-items: center; + justify-content: center; + font-weight: bold; + font-family: serif; + font-size: 16px; +} +.window-captcha__content__body__coordinator .pointer:hover span { + font-size: 0; +} +.window-captcha__content__body__coordinator .pointer:hover span:after { + content: "X"; + font-size: 16px; + color: #961b1b; +} +.window-captcha__content__body__error { + border: 1px solid #961b1b; + color: #961b1b; + font-size: 16px; + font-weight: bold; + margin: 20px; + padding: 20px; +} +.window-captcha__content__body .error-message { + color: #961b1b; + font-size: 16px; + font-weight: bold; + padding: 20px; +} +@keyframes sp-anime { + 100% { + transform: rotate(360deg); + } +} \ No newline at end of file