 |

29.07.2025, 13:51
|
|
Новичок
Регистрация: 24.07.2025
Сообщений: 6
С нами:
426411
Репутация:
3
|
|
Что делает бот - При команде /start показывает картинку-капчу.
- Есть кнопка «Обновить капчу», чтобы получить новое изображение.
- Пользователь вводит текст с картинки.
- На ввод даётся три попытки.
- Пока капча не решена, остальные команды не работают.
- После правильного ввода бот снимает блокировку и принимает любые команды.
captcha telegram bot:
Код:
import
os
,
logging
from
telegram
import
Update
,
InlineKeyboardMarkup
,
InlineKeyboardButton
,
InputMediaPhoto
from
telegram
.
ext
import
(
Application
,
CommandHandler
,
MessageHandler
,
CallbackContext
,
CallbackQueryHandler
,
filters
)
from
captcha
.
image
import
ImageCaptcha
TOKEN
=
"Сюда ты должен вставить свой токен бота"
CAPTCHA_FOLDER
=
"captchas"
os
.
makedirs
(
CAPTCHA_FOLDER
,
exist_ok
=
True
)
user_data
=
{
}
logging
.
basicConfig
(
format
=
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
,
level
=
logging
.
INFO
)
logger
=
logging
.
getLogger
(
__name__
)
def
generate_captcha
(
user_id
:
int
)
:
captcha_text
=
os
.
urandom
(
3
)
.
hex
(
)
.
upper
(
)
image
=
ImageCaptcha
(
width
=
300
,
height
=
150
)
file_path
=
os
.
path
.
join
(
CAPTCHA_FOLDER
,
f"{user_id}_captcha.png"
)
image
.
write
(
captcha_text
,
file_path
)
return
captcha_text
,
file_path
async
def
start
(
update
:
Update
,
context
:
CallbackContext
)
:
user_id
=
update
.
effective_user
.
id
captcha_text
,
captcha_path
=
generate_captcha
(
user_id
)
user_data
[
user_id
]
=
{
'captcha'
:
captcha_text
,
'passed'
:
False
,
'attempts'
:
0
}
keyboard
=
[
[
InlineKeyboardButton
(
"Обновить капчу"
,
callback_data
=
'refresh'
)
]
]
with
open
(
captcha_path
,
'rb'
)
as
photo
:
await
update
.
message
.
reply_photo
(
photo
=
photo
,
caption
=
"🔐 Для использования бота решите капчу:\n➖ Отправьте текст с картинки\n🔄 Если не видно — обновите капчу"
,
reply_markup
=
InlineKeyboardMarkup
(
keyboard
)
)
async
def
refresh_captcha
(
update
:
Update
,
context
:
CallbackContext
)
:
query
=
update
.
callback_query
await
query
.
answer
(
)
user_id
=
query
.
from_user
.
id
captcha_text
,
captcha_path
=
generate_captcha
(
user_id
)
user_data
[
user_id
]
=
{
'captcha'
:
captcha_text
,
'passed'
:
False
,
'attempts'
:
user_data
.
get
(
user_id
,
{
}
)
.
get
(
'attempts'
,
0
)
}
keyboard
=
[
[
InlineKeyboardButton
(
"Обновить капчу"
,
callback_data
=
'refresh'
)
]
]
with
open
(
captcha_path
,
'rb'
)
as
photo
:
await
query
.
edit_message_media
(
media
=
InputMediaPhoto
(
media
=
photo
)
,
reply_markup
=
InlineKeyboardMarkup
(
keyboard
)
)
await
query
.
edit_message_caption
(
caption
=
"🔄 Капча обновлена! Отправьте текст с картинки:"
,
reply_markup
=
InlineKeyboardMarkup
(
keyboard
)
)
async
def
verify_captcha
(
update
:
Update
,
context
:
CallbackContext
)
:
user_id
=
update
.
message
.
from_user
.
id
user_input
=
update
.
message
.
text
.
strip
(
)
.
upper
(
)
if
user_data
.
get
(
user_id
,
{
}
)
.
get
(
'passed'
)
:
await
update
.
message
.
reply_text
(
"✅ Вы уже прошли проверку!"
)
return
if
user_id
not
in
user_data
:
await
update
.
message
.
reply_text
(
"⚠️ Сначала запустите /start"
)
return
captcha_data
=
user_data
[
user_id
]
if
captcha_data
[
'attempts'
]
>=
3
:
await
update
.
message
.
reply_text
(
"🚫 Превышено число попыток! Запустите /start заново"
)
return
if
user_input
==
captcha_data
[
'captcha'
]
:
user_data
[
user_id
]
[
'passed'
]
=
True
await
update
.
message
.
reply_text
(
"✅ Капча пройдена успешно!\n\nТеперь вы можете использовать бота!\nПопробуйте команду: /hello"
)
else
:
user_data
[
user_id
]
[
'attempts'
]
+=
1
attempts_left
=
3
-
user_data
[
user_id
]
[
'attempts'
]
await
update
.
message
.
reply_text
(
f"❌ Неверно! Осталось попыток:{attempts_left}\nПопробуйте еще раз или обновите капчу"
)
async
def
hello
(
update
:
Update
,
context
:
CallbackContext
)
:
user_id
=
update
.
effective_user
.
id
if
user_data
.
get
(
user_id
,
{
}
)
.
get
(
'passed'
)
:
await
update
.
message
.
reply_text
(
f"👋 Привет,{update.effective_user.first_name}!"
)
else
:
await
update
.
message
.
reply_text
(
"🚫 Сначала пройдите капчу через /start"
)
def
main
(
)
:
application
=
Application
.
builder
(
)
.
token
(
TOKEN
)
.
build
(
)
application
.
add_handler
(
CommandHandler
(
"start"
,
start
)
)
application
.
add_handler
(
CommandHandler
(
"hello"
,
hello
)
)
application
.
add_handler
(
MessageHandler
(
filters
.
TEXT
&
~
filters
.
COMMAND
,
verify_captcha
)
)
application
.
add_handler
(
CallbackQueryHandler
(
refresh_captcha
,
pattern
=
'^refresh$'
)
)
application
.
run_polling
(
)
if
__name__
==
'__main__'
:
main
(
)

|
|
|

30.07.2025, 22:28
|
|
Участник форума
Регистрация: 29.12.2020
Сообщений: 295
С нами:
2827988
Репутация:
98
|
|
Выглядит не плохо, но я бы доработал. Любой OCR сможет распознать контент капчи (не говоря уже об ИИ). Так же в 99% капчей работающих на текст-ввод - есть фаззи матчинг, а у тебя же его нету, из-за чего человек, который будет проходить капчу скажет "да идёт на*** эта ебанная капча блять, я же "правильно ввёл"..."
Так же зачем лишние R/W операции на диск при создании капчи? Сразу в память её пиши и используй, а потом сноси.
1753900111823.pngDeps · 30 Июл 2025 в 21:28' data-fancybox="lb-post-1625545" data-lb-caption-extra-html="" data-lb-sidebar-href="" data-single-image="1" data-src="https://www.blast.hk/attachments/275413/" style="cursor: pointer;" title="1753900111823.png">

|
|
|

31.07.2025, 15:01
|
|
Новичок
Регистрация: 24.07.2025
Сообщений: 6
С нами:
426411
Репутация:
3
|
|
Теперь капча генерируется полностью в памяти, никаких временных файлов на диске — всё стало быстрее и чище.
Картинка капчи стала сложнее: добавил шум, линии, точки, блюр и разные шрифты. Теперь распознать её ботом или через OCR стало намного труднее.
Убрал все лишние операции с диском, теперь всё работает через оперативную память.
В целом код стал проще, быстрее и надёжнее.
1753959632595.pngNGSH · 31 Июл 2025 в 14:01' data-fancybox="lb-post-1625731" data-lb-caption-extra-html="" data-lb-sidebar-href="" data-single-image="1" data-src="https://www.blast.hk/attachments/275477/" style="cursor: pointer;" title="1753959632595.png">
captcha telegram bot::
Код:
import
os
import
logging
import
random
import
io
from
PIL
import
Image
,
ImageDraw
,
ImageFont
,
ImageFilter
from
telegram
import
Update
,
InlineKeyboardMarkup
,
InlineKeyboardButton
,
InputMediaPhoto
from
telegram
.
ext
import
(
Application
,
CommandHandler
,
MessageHandler
,
CallbackContext
,
CallbackQueryHandler
,
filters
)
TOKEN
=
"Сюда ты должен вставить свой токен бота"
user_data
=
{
}
logging
.
basicConfig
(
format
=
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
,
level
=
logging
.
INFO
)
logger
=
logging
.
getLogger
(
__name__
)
def
generate_captcha
(
user_id
:
int
)
:
captcha_text
=
''
.
join
(
random
.
choices
(
'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'
,
k
=
5
)
)
width
,
height
=
220
,
100
image
=
Image
.
new
(
'RGB'
,
(
width
,
height
)
,
(
255
,
255
,
255
)
)
draw
=
ImageDraw
.
Draw
(
image
)
fonts
=
[
ImageFont
.
truetype
(
"arial.ttf"
,
48
)
,
ImageFont
.
truetype
(
"arialbd.ttf"
,
48
)
,
]
for
i
,
char
in
enumerate
(
captcha_text
)
:
font
=
random
.
choice
(
fonts
)
x
=
20
+
i
*
35
+
random
.
randint
(
-
5
,
5
)
y
=
20
+
random
.
randint
(
-
10
,
10
)
draw
.
text
(
(
x
,
y
)
,
char
,
font
=
font
,
fill
=
(
random
.
randint
(
0
,
120
)
,
random
.
randint
(
0
,
120
)
,
random
.
randint
(
0
,
120
)
)
)
for
_
in
range
(
8
)
:
x1
,
y1
=
random
.
randint
(
0
,
width
)
,
random
.
randint
(
0
,
height
)
x2
,
y2
=
random
.
randint
(
0
,
width
)
,
random
.
randint
(
0
,
height
)
draw
.
line
(
(
(
x1
,
y1
)
,
(
x2
,
y2
)
)
,
fill
=
(
random
.
randint
(
100
,
200
)
,
random
.
randint
(
100
,
200
)
,
random
.
randint
(
100
,
200
)
)
,
width
=
2
)
for
_
in
range
(
300
)
:
x
,
y
=
random
.
randint
(
0
,
width
)
,
random
.
randint
(
0
,
height
)
draw
.
point
(
(
x
,
y
)
,
fill
=
(
random
.
randint
(
0
,
255
)
,
random
.
randint
(
0
,
255
)
,
random
.
randint
(
0
,
255
)
)
)
image
=
image
.
filter
(
ImageFilter
.
GaussianBlur
(
1.2
)
)
img_bytes
=
io
.
BytesIO
(
)
image
.
save
(
img_bytes
,
format
=
'PNG'
)
img_bytes
.
seek
(
0
)
return
captcha_text
,
img_bytes
def
fuzzy_match
(
a
,
b
,
max_distance
=
1
)
:
if
len
(
a
)
!=
len
(
b
)
:
return
False
return
sum
(
x
!=
y
for
x
,
y
in
zip
(
a
,
b
)
)
=
3
:
await
update
.
message
.
reply_text
(
"🚫 Превышено число попыток! Запустите /start заново"
)
return
if
fuzzy_match
(
user_input
,
captcha_data
[
'captcha'
]
)
:
user_data
[
user_id
]
[
'passed'
]
=
True
await
update
.
message
.
reply_text
(
"✅ Капча пройдена успешно!\n\nТеперь вы можете использовать бота!\nПопробуйте команду: /hello"
)
else
:
user_data
[
user_id
]
[
'attempts'
]
+=
1
attempts_left
=
3
-
user_data
[
user_id
]
[
'attempts'
]
await
update
.
message
.
reply_text
(
f"❌ Неверно! Осталось попыток:{attempts_left}\nПопробуйте еще раз или обновите капчу"
)
async
def
hello
(
update
:
Update
,
context
:
CallbackContext
)
:
user_id
=
update
.
effective_user
.
id
if
user_data
.
get
(
user_id
,
{
}
)
.
get
(
'passed'
)
:
await
update
.
message
.
reply_text
(
f"👋 Привет,{update.effective_user.first_name}!"
)
else
:
await
update
.
message
.
reply_text
(
"🚫 Сначала пройдите капчу через /start"
)
def
main
(
)
:
application
=
Application
.
builder
(
)
.
token
(
TOKEN
)
.
build
(
)
application
.
add_handler
(
CommandHandler
(
"start"
,
start
)
)
application
.
add_handler
(
CommandHandler
(
"hello"
,
hello
)
)
application
.
add_handler
(
MessageHandler
(
filters
.
TEXT
&
~
filters
.
COMMAND
,
verify_captcha
)
)
application
.
add_handler
(
CallbackQueryHandler
(
refresh_captcha
,
pattern
=
'^refresh$'
)
)
application
.
run_polling
(
)
if
__name__
==
'__main__'
:
main
(
)
|
|
|
|
 |
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|