Coverage for /home/marco/Code/django-simple-captcha/captcha/helpers.py: 68.67%
71 statements
« prev ^ index » next coverage.py v7.6.5, created at 2024-11-15 09:22 +0100
« prev ^ index » next coverage.py v7.6.5, created at 2024-11-15 09:22 +0100
1import random
3from django.urls import reverse
5from captcha.conf import settings
8def math_challenge():
9 operators = ("+", "*", "-")
10 operands = (random.randint(1, 10), random.randint(1, 10))
11 operator = random.choice(operators)
12 if operands[0] < operands[1] and "-" == operator:
13 operands = (operands[1], operands[0])
14 challenge = "%d%s%d" % (operands[0], operator, operands[1])
15 return (
16 "{}=".format(challenge.replace("*", settings.CAPTCHA_MATH_CHALLENGE_OPERATOR)),
17 str(eval(challenge)),
18 )
21def random_char_challenge():
22 chars, ret = "abcdefghijklmnopqrstuvwxyz", ""
23 for i in range(settings.CAPTCHA_LENGTH):
24 ret += random.choice(chars)
25 return ret.upper(), ret
28def unicode_challenge():
29 chars, ret = "äàáëéèïíîöóòüúù", ""
30 for i in range(settings.CAPTCHA_LENGTH):
31 ret += random.choice(chars)
32 return ret.upper(), ret
35def word_challenge():
36 fd = open(settings.CAPTCHA_WORDS_DICTIONARY, "r")
37 lines = fd.readlines()
38 fd.close()
39 while True:
40 word = random.choice(lines).strip()
41 if (
42 len(word) >= settings.CAPTCHA_DICTIONARY_MIN_LENGTH
43 and len(word) <= settings.CAPTCHA_DICTIONARY_MAX_LENGTH
44 ):
45 break
46 return word.upper(), word.lower()
49def huge_words_and_punctuation_challenge():
50 "Yay, undocumneted. Mostly used to test Issue 39 - http://code.google.com/p/django-simple-captcha/issues/detail?id=39"
51 fd = open(settings.CAPTCHA_WORDS_DICTIONARY, "rb")
52 lines = fd.readlines()
53 fd.close()
54 word = ""
55 while True:
56 word1 = random.choice(lines).strip()
57 word2 = random.choice(lines).strip()
58 punct = random.choice(settings.CAPTCHA_PUNCTUATION)
59 word = "%s%s%s" % (word1, punct, word2)
60 if (
61 len(word) >= settings.CAPTCHA_DICTIONARY_MIN_LENGTH
62 and len(word) <= settings.CAPTCHA_DICTIONARY_MAX_LENGTH
63 ):
64 break
65 return word.upper(), word.lower()
68def noise_arcs(draw, image):
69 size = image.size
70 draw.arc([-20, -20, size[0], 20], 0, 295, fill=settings.CAPTCHA_FOREGROUND_COLOR)
71 draw.line(
72 [-20, 20, size[0] + 20, size[1] - 20], fill=settings.CAPTCHA_FOREGROUND_COLOR
73 )
74 draw.line([-20, 0, size[0] + 20, size[1]], fill=settings.CAPTCHA_FOREGROUND_COLOR)
75 return draw
78def noise_dots(draw, image):
79 size = image.size
80 for p in range(int(size[0] * size[1] * 0.1)):
81 draw.point(
82 (random.randint(0, size[0]), random.randint(0, size[1])),
83 fill=settings.CAPTCHA_FOREGROUND_COLOR,
84 )
85 return draw
88def noise_null(draw, image):
89 return draw
92def random_letter_color_challenge(idx, plaintext_captcha):
93 # Generate colorful but balanced RGB values
94 red = random.randint(64, 200)
95 green = random.randint(64, 200)
96 blue = random.randint(64, 200)
98 # Ensure at least one channel is higher to make it colorful
99 channels = [red, green, blue]
100 random.shuffle(channels)
101 channels[0] = random.randint(150, 255)
103 # Format the color as a hex string
104 return f"#{channels[0]:02X}{channels[1]:02X}{channels[2]:02X}"
107def post_smooth(image):
108 from PIL import ImageFilter
110 return image.filter(ImageFilter.SMOOTH)
113def captcha_image_url(key):
114 """Return url to image. Need for ajax refresh and, etc"""
115 return reverse("captcha-image", args=[key])
118def captcha_audio_url(key):
119 """Return url to image. Need for ajax refresh and, etc"""
120 return reverse("captcha-audio", args=[key])