Files
webments/bots/simple-captcha.js

108 lines
4.7 KiB
JavaScript

class SimpleCaptcha extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
this.render();
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
display: inline-block;
font-family: sans-serif;
--captcha-border: #ccc;
--captcha-bg: #f9f9f9;
--captcha-gap: 6px;
}
.captcha-wrapper {
display: flex;
align-items: center;
gap: var(--captcha-gap);
}
img {
border: 1px solid var(--captcha-border);
border-radius: 4px;
height: 40px;
object-fit: cover;
}
input {
flex: 1;
padding: 6px 8px;
border: 1px solid var(--captcha-border);
border-radius: 4px;
}
button {
padding: 6px 10px;
border-radius: 4px;
border: 1px solid var(--captcha-border);
background: var(--captcha-bg);
cursor: pointer;
}
</style>
<div class="captcha-wrapper">
<img id="img" src="captcha.php?${Date.now()}" alt="Captcha">
<input id="input" placeholder="Enter code" autocomplete="off">
<button id="refresh" title="Refresh Captcha">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="8" height="8" viewBox="0 0 256 256" xml:space="preserve">
<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1; " transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)">
<path d="M 81.521 31.109 c -0.86 -1.73 -2.959 -2.438 -4.692 -1.575 c -1.73 0.86 -2.436 2.961 -1.575 4.692 c 2.329 4.685 3.51 9.734 3.51 15.01 C 78.764 67.854 63.617 83 45 83 S 11.236 67.854 11.236 49.236 c 0 -16.222 11.501 -29.805 26.776 -33.033 l -3.129 4.739 c -1.065 1.613 -0.62 3.784 0.992 4.85 c 0.594 0.392 1.264 0.579 1.926 0.579 c 1.136 0 2.251 -0.553 2.924 -1.571 l 7.176 -10.87 c 0.001 -0.001 0.001 -0.002 0.002 -0.003 l 0.018 -0.027 c 0.063 -0.096 0.106 -0.199 0.159 -0.299 c 0.049 -0.093 0.108 -0.181 0.149 -0.279 c 0.087 -0.207 0.152 -0.419 0.197 -0.634 c 0.009 -0.041 0.008 -0.085 0.015 -0.126 c 0.031 -0.182 0.053 -0.364 0.055 -0.547 c 0 -0.014 0.004 -0.028 0.004 -0.042 c 0 -0.066 -0.016 -0.128 -0.019 -0.193 c -0.008 -0.145 -0.018 -0.288 -0.043 -0.431 c -0.018 -0.097 -0.045 -0.189 -0.071 -0.283 c -0.032 -0.118 -0.065 -0.236 -0.109 -0.35 c -0.037 -0.095 -0.081 -0.185 -0.125 -0.276 c -0.052 -0.107 -0.107 -0.211 -0.17 -0.313 c -0.054 -0.087 -0.114 -0.168 -0.175 -0.25 c -0.07 -0.093 -0.143 -0.183 -0.223 -0.27 c -0.074 -0.08 -0.153 -0.155 -0.234 -0.228 c -0.047 -0.042 -0.085 -0.092 -0.135 -0.132 L 36.679 0.775 c -1.503 -1.213 -3.708 -0.977 -4.921 0.53 c -1.213 1.505 -0.976 3.709 0.53 4.921 l 3.972 3.2 C 17.97 13.438 4.236 29.759 4.236 49.236 C 4.236 71.714 22.522 90 45 90 s 40.764 -18.286 40.764 -40.764 C 85.764 42.87 84.337 36.772 81.521 31.109 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round"/>
</g>
</svg>
</button>
<button id="submit" title="Submit Captcha">Submit</button>
</div>
`;
const img = this.shadowRoot.getElementById("img");
img.addEventListener("click", () => this.refresh());
this.shadowRoot.getElementById("refresh")
.addEventListener("click", () => this.refresh());
this.shadowRoot.getElementById("submit")
.addEventListener("click", () => this.handleSubmit());
}
refresh() {
const img = this.shadowRoot.getElementById("img");
img.src = "captcha.php?" + Date.now();
this.shadowRoot.getElementById("input").value = "";
}
async validate() {
const input = this.shadowRoot.getElementById("input").value.trim();
if (!input) return false;
const formData = new FormData();
formData.append("captcha", input);
try {
const res = await fetch("validate.php", { method: "POST", body: formData });
const data = await res.json();
return data.status === "valid";
} catch (err) {
console.error("Captcha validation failed:", err);
return false;
}
}
async handleSubmit() {
const isValid = await this.validate();
if (isValid) {
this.dispatchEvent(new CustomEvent("valid"));
this.refresh();
} else {
this.dispatchEvent(new CustomEvent("invalid"));
this.refresh();
}
}
}
customElements.define("simple-captcha", SimpleCaptcha);