FreeCAPTCHA/freecaptcha/captcha.py

138 lines
3.1 KiB
Python
Raw Permalink Normal View History

2022-04-11 23:44:17 -04:00
import random
import os
from PIL import Image
import base64
from io import BytesIO
2023-06-29 17:01:21 -04:00
from collections import deque
2022-04-11 23:44:17 -04:00
2023-06-12 09:56:17 -04:00
import os
def generate_layers(images, index=0):
if len(images) == 0:
return ''
return f'''<label>
<input id="layer{index}" type="radio" name="captcha{index}" value="{index}">
2023-06-29 17:01:21 -04:00
<img src="data:image/png;base64,{images[0]}"></img>
2023-06-12 09:56:17 -04:00
{generate_layers(images[1:], index+1)}
</label>
'''
def generate_captcha_html(images):
html = ''
html_prelude = '''
<style>
.grid {
display: grid;
grid-template-columns: repeat(3, 0fr);
}
div > div {
padding: 10px;
}
img {
background-color: white;
}
'''
generated_css = ''
for index, image in enumerate(images):
generated_css += f'''
/* ---- CURRENT LAYER: {index} ---- */
#layer{index}[type=radio] {{
position: absolute;
opacity: 0;
width: 0;
height: 0;
}}
#layer{index}[type=radio] + img {{
cursor: pointer;
padding: 5px;
position: absolute;
background-color: white;
}}
/* CHECKED STYLES */
#layer{index}[type=radio]:checked + img {{
z-index: -1000;
}}
'''
middle_boilerplate = '''
#root {
width: fit-content;
/* To adjust the height as well */
height: fit-content;
}
</style>
<body>
<div id="root">
<form method="POST">
<div class='grid'>
'''
generated_recursive_layers = generate_layers(images)
html_postscript = '''
<input style="position: absolute; top: 300px" type="submit">Submit</input>
</form>
</div>
</body>'''
html = html_prelude + generated_css + middle_boilerplate + generated_recursive_layers + html_postscript
return html
2022-04-11 23:44:17 -04:00
# Angles we'll rotate the original by
# when we create n rotations
def calculate_angles(n):
return list(range(0, 360, 360 // n))
def rotate_img(img_path, angle):
original_img = Image.open(img_path)
rotated = original_img.rotate(angle)
buffered = BytesIO()
rotated.save(buffered, format="PNG")
b64_rot = base64.b64encode(buffered.getvalue())
return b64_rot.decode("utf-8")
def captchafy(img_path, n=6):
angles = calculate_angles(n)
2023-06-29 17:01:21 -04:00
rotated_imgs = deque(
[rotate_img(img_path, angle) for angle in angles][::-1] * 3
)
random_shift = random.randint(1, n)
2022-04-11 23:44:17 -04:00
2023-06-29 17:01:21 -04:00
rotated_imgs.rotate(-random_shift)
return random_shift % n, rotated_imgs
2022-04-11 23:44:17 -04:00
def random_image(dir='images/'):
dir_contents = os.listdir(dir)
random_image = random.choice(dir_contents)
return dir + random_image
2023-06-12 09:56:17 -04:00
## lol what does this do???
2022-04-11 23:44:17 -04:00
def resize_dir(size=150, dir='images/'):
for img_file in os.listdir(dir):
img = Image.open(dir + img_file)
width, height = img.size
print(width, height)
if not (width > size or height > size):
continue
img.thumbnail((size, size),Image.ANTIALIAS)
img.save(dir + img_file)
2023-06-12 09:56:17 -04:00
if __name__ == '__main__':
img_path = random_image(dir='images/')
answer, options = captchafy(img_path)
for i, img_b64 in enumerate(options):
print(img_b64)
im = Image.open(BytesIO(base64.b64decode(img_b64)))
im.save(f'images/image{i}.png')