Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F618495
join_captcha.lua
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
5 KB
Referenced Files
None
Subscribers
None
join_captcha.lua
View Options
--[[
mattata v2.0 - Join Captcha Plugin
Handles captcha verification for new members joining the group.
]]
local
plugin
=
{}
plugin
.
name
=
'join_captcha'
plugin
.
category
=
'admin'
plugin
.
description
=
'Captcha challenge for new members'
plugin
.
commands
=
{}
plugin
.
help
=
''
plugin
.
group_only
=
true
plugin
.
admin_only
=
false
local
json
=
require
(
'dkjson'
)
-- Generate a simple math captcha
local
function
generate_captcha
()
math.randomseed
(
os.time
())
local
a
=
math.random
(
1
,
20
)
local
b
=
math.random
(
1
,
20
)
local
operators
=
{
'+'
,
'-'
}
local
op
=
operators
[
math.random
(
1
,
2
)]
local
answer
if
op
==
'+'
then
answer
=
a
+
b
else
-- Ensure non-negative result
if
a
<
b
then
a
,
b
=
b
,
a
end
answer
=
a
-
b
end
return
string.format
(
'%d %s %d'
,
a
,
op
,
b
),
tostring
(
answer
)
end
-- Generate wrong answers for the keyboard
local
function
generate_options
(
correct_answer
)
local
options
=
{
correct_answer
}
local
correct_num
=
tonumber
(
correct_answer
)
while
#
options
<
4
do
local
wrong
=
correct_num
+
math.random
(
-
5
,
5
)
if
wrong
~=
correct_num
and
wrong
>=
0
then
local
str
=
tostring
(
wrong
)
local
duplicate
=
false
for
_
,
v
in
ipairs
(
options
)
do
if
v
==
str
then
duplicate
=
true
;
break
end
end
if
not
duplicate
then
table.insert
(
options
,
str
)
end
end
end
-- Shuffle
for
i
=
#
options
,
2
,
-
1
do
local
j
=
math.random
(
1
,
i
)
options
[
i
],
options
[
j
]
=
options
[
j
],
options
[
i
]
end
return
options
end
function
plugin
.
on_member_join
(
api
,
message
,
ctx
)
if
not
ctx
.
is_group
then
return
end
-- Check if captcha is enabled
local
enabled
=
ctx
.
db
.
execute
(
"SELECT value FROM chat_settings WHERE chat_id = $1 AND key = 'captcha_enabled'"
,
{
message
.
chat
.
id
}
)
if
not
enabled
or
#
enabled
==
0
or
enabled
[
1
].
value
~=
'true'
then
return
end
if
not
require
(
'src.core.permissions'
).
can_restrict
(
api
,
message
.
chat
.
id
)
then
return
end
local
timeout_result
=
ctx
.
db
.
execute
(
"SELECT value FROM chat_settings WHERE chat_id = $1 AND key = 'captcha_timeout'"
,
{
message
.
chat
.
id
}
)
local
timeout
=
(
timeout_result
and
#
timeout_result
>
0
)
and
tonumber
(
timeout_result
[
1
].
value
)
or
300
for
_
,
new_member
in
ipairs
(
message
.
new_chat_members
)
do
if
new_member
.
is_bot
then
goto
continue
end
-- Restrict the new member
api
.
restrict_chat_member
(
message
.
chat
.
id
,
new_member
.
id
,
{
can_send_messages
=
false
,
can_send_audios
=
false
,
can_send_documents
=
false
,
can_send_photos
=
false
,
can_send_videos
=
false
,
can_send_video_notes
=
false
,
can_send_voice_notes
=
false
,
can_send_polls
=
false
,
can_send_other_messages
=
false
,
can_add_web_page_previews
=
false
},
{
until_date
=
os.time
()
+
timeout
})
-- Generate captcha
local
question
,
answer
=
generate_captcha
()
local
options
=
generate_options
(
answer
)
-- Build keyboard
local
keyboard
=
{
inline_keyboard
=
{
{}
}
}
for
_
,
opt
in
ipairs
(
options
)
do
table.insert
(
keyboard
.
inline_keyboard
[
1
],
{
text
=
opt
,
callback_data
=
string.format
(
'join_captcha:%s:%s:%s'
,
message
.
chat
.
id
,
new_member
.
id
,
opt
)
})
end
local
tools
=
require
(
'telegram-bot-lua.tools'
)
local
text
=
string.format
(
'Welcome, <a href="tg://user?id=%d">%s</a>! Please solve this to verify you
\'
re human:
\n\n
<b>What is %s?</b>
\n\n
You have %d seconds.'
,
new_member
.
id
,
tools
.
escape_html
(
new_member
.
first_name
),
question
,
timeout
)
local
sent
=
api
.
send_message
(
message
.
chat
.
id
,
text
,
'html'
,
false
,
false
,
nil
,
json
.
encode
(
keyboard
))
-- Store captcha state
if
sent
and
sent
.
result
then
ctx
.
session
.
set_captcha
(
message
.
chat
.
id
,
new_member
.
id
,
answer
,
sent
.
result
.
message_id
,
timeout
)
end
::
continue
::
end
end
function
plugin
.
on_callback_query
(
api
,
callback_query
,
message
,
ctx
)
local
data
=
callback_query
.
data
if
not
data
then
return
end
local
chat_id
,
user_id
,
selected
=
data
:
match
(
'^(%-?%d+):(%d+):(.+)$'
)
if
not
chat_id
then
return
end
chat_id
=
tonumber
(
chat_id
)
user_id
=
tonumber
(
user_id
)
-- Only the joining user can answer
if
callback_query
.
from
.
id
~=
user_id
then
return
api
.
answer_callback_query
(
callback_query
.
id
,
'This captcha is not for you.'
)
end
local
captcha
=
ctx
.
session
.
get_captcha
(
chat_id
,
user_id
)
if
not
captcha
then
return
api
.
answer_callback_query
(
callback_query
.
id
,
'This captcha has expired.'
)
end
if
selected
==
captcha
.
text
then
-- Correct answer - unrestrict user
api
.
restrict_chat_member
(
chat_id
,
user_id
,
{
can_send_messages
=
true
,
can_send_audios
=
true
,
can_send_documents
=
true
,
can_send_photos
=
true
,
can_send_videos
=
true
,
can_send_video_notes
=
true
,
can_send_voice_notes
=
true
,
can_send_polls
=
true
,
can_send_other_messages
=
true
,
can_add_web_page_previews
=
true
})
ctx
.
session
.
clear_captcha
(
chat_id
,
user_id
)
local
tools
=
require
(
'telegram-bot-lua.tools'
)
api
.
edit_message_text
(
message
.
chat
.
id
,
message
.
message_id
,
string.format
(
'<a href="tg://user?id=%d">%s</a> has been verified. Welcome!'
,
user_id
,
tools
.
escape_html
(
callback_query
.
from
.
first_name
)
),
'html'
)
api
.
answer_callback_query
(
callback_query
.
id
,
'Correct! Welcome to the group.'
)
else
-- Wrong answer
api
.
answer_callback_query
(
callback_query
.
id
,
'Wrong answer. Try again!'
)
end
end
return
plugin
File Metadata
Details
Attached
Mime Type
text/html
Expires
Sat, Nov 14, 3:10 PM (1 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
135857
Default Alt Text
join_captcha.lua (5 KB)
Attached To
Mode
R69 mattata
Attached
Detach File
Event Timeline