aboutsummaryrefslogtreecommitdiffstats
path: root/templates/index.html
blob: c5cea6b0d2a84da02bdc37a34856624386ef9794 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>4gCAPTCHA</title>
    <style>
        body { font-family: sans-serif; display: flex; flex-direction: column; align-items: center; margin-top: 50px; background: #f4f4f4;}
        #captcha-container { position: relative; width: 400px; height: 427px; border: 1px solid #ccc; margin-bottom: 20px; background: #fff; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
        #captcha-image { width: 100%; height: 100%; pointer-events: none; }
        #grid { position: absolute; top: 27px; left: 0; width: 400px; height: 400px; display: grid; grid-template-columns: repeat(4, 100px); grid-template-rows: repeat(4, 100px); }
        .cell { width: 100px; height: 100px; box-sizing: border-box; cursor: pointer; border: 2px solid transparent; transition: all 0.1s; }
        .cell:hover { border: 2px solid rgba(255, 255, 255, 0.5); }
        .cell.selected { border: 3px solid #00ff00; background: rgba(0, 255, 0, 0.25); }
        #controls { display: flex; gap: 10px; }
        button { padding: 10px 20px; cursor: pointer; font-size: 16px; border: none; border-radius: 4px; background: #007bff; color: white; }
        button:hover { background: #0056b3; }
        #result { margin-top: 20px; font-weight: bold; font-size: 18px; }
        p { max-width: 600px; text-align: center; line-height: 1.5; color: #444; margin-bottom: 25px; }
        a { color: #007bff; text-decoration: none; }
        a:hover { text-decoration: underline; }
    </style>
</head>
<body>
    <h2>4gCAPTCHA</h2>
    <p>4gcaptcha is a captcha server based on the one used in <a href="https://git.lolcat.ca/lolcat/4get">4get</a><br/>
        The module below demonstrates what a captcha could look like.
        <br/>Please refer to the <a href="https://git.moekyun.me/4captcha/about">README on the repo for more info</a>
    </p>
    <div id="captcha-container">
        <img id="captcha-image" src="" alt="Loading captcha..." />
        <div id="grid"></div>
    </div>
    <div id="controls">
        <button onclick="loadCaptcha()" style="background: #6c757d;">Reload</button>
        <button onclick="verifyCaptcha()">Verify</button>
    </div>
    <div id="result"></div>
    <script>
        let currentToken = '';
        let selectedCells = new Set();
        const grid = document.getElementById('grid');
        for (let i = 0; i < 16; i++) {
            const cell = document.createElement('div');
            cell.className = 'cell';
            cell.dataset.index = i;
            cell.onclick = () => toggleCell(cell, i);
            grid.appendChild(cell);
        }
        function toggleCell(cell, index) {
            if (selectedCells.has(index)) {
                selectedCells.delete(index);
                cell.classList.remove('selected');
            } else {
                selectedCells.add(index);
                cell.classList.add('selected');
            }
        }
        async function loadCaptcha() {
            selectedCells.clear();
            document.querySelectorAll('.cell').forEach(c => c.classList.remove('selected'));
            document.getElementById('result').innerText = 'Loading...';
            document.getElementById('result').style.color = '#333';
            try {
                const res = await fetch('/generate');
                const data = await res.json();
                if (data.error) throw new Error(data.error);
                currentToken = data.token;
                document.getElementById('captcha-image').src = data.image;
                document.getElementById('result').innerText = '';
            } catch (err) {
                document.getElementById('result').innerText = 'Error: ' + err.message;
                document.getElementById('result').style.color = 'red';
            }
        }
        async function verifyCaptcha() {
            if (!currentToken) return;
            try {
                const res = await fetch('/verify', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ token: currentToken, answers: Array.from(selectedCells) })
                });
                const data = await res.json();
                if (data.success) {
                    document.getElementById('result').style.color = 'green';
                    document.getElementById('result').innerText = 'Success! You passed the captcha.';
                } else {
                    document.getElementById('result').style.color = 'red';
                    document.getElementById('result').innerText = 'Failed: ' + (data.error || 'Incorrect answers') + '. Reloading...';
                    setTimeout(loadCaptcha, 1500);
                }
            } catch (err) {
                document.getElementById('result').innerText = 'Error: ' + err.message;
                document.getElementById('result').style.color = 'red';
            }
        }
        loadCaptcha();
    </script>
</body>
</html>
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage