mirror of
https://github.com/Xtao-Labs/sticker-captcha-bot.git
synced 2024-11-26 02:10:57 +00:00
refa: clean verify user message
This commit is contained in:
parent
4f0607c034
commit
f1f10b454a
@ -1,5 +1,4 @@
|
|||||||
import contextlib
|
import contextlib
|
||||||
from datetime import datetime, timedelta
|
|
||||||
|
|
||||||
from cashews import cache
|
from cashews import cache
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
@ -8,17 +7,45 @@ from pyrogram.types import ChatMemberUpdated
|
|||||||
|
|
||||||
from pyromod.utils.errors import TimeoutConversationError
|
from pyromod.utils.errors import TimeoutConversationError
|
||||||
from sticker.languages import MSG_PUBLIC, ADMIN_MSG, MSG, VERIFY_TIME
|
from sticker.languages import MSG_PUBLIC, ADMIN_MSG, MSG, VERIFY_TIME
|
||||||
from sticker.scheduler import add_delete_message_job
|
from sticker.scheduler import add_ban_chat_member_job
|
||||||
from sticker.service_message import ServiceMessage
|
from sticker.service_message import ServiceMessage
|
||||||
from sticker.single_utils import Client
|
from sticker.single_utils import Client, Message
|
||||||
from sticker import bot, log
|
from sticker import bot, log, LogAction
|
||||||
|
|
||||||
|
|
||||||
|
async def start_verify(client: "Client", chat, user):
|
||||||
|
key = f"wait:{chat.id}:{user.id}"
|
||||||
|
await cache.set(key, "True", expire=VERIFY_TIME + 5)
|
||||||
|
try:
|
||||||
|
msg: "Message" = await client.send_message(
|
||||||
|
chat.id, MSG % (user.mention, user.mention)
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
|
await log(chat, user, LogAction.REQUEST)
|
||||||
|
try:
|
||||||
|
msg_: "Message" = await client.listen(
|
||||||
|
chat.id, filters=filters.user(user.id), timeout=VERIFY_TIME
|
||||||
|
)
|
||||||
|
await msg.delay_delete(1)
|
||||||
|
await msg_.delay_delete(1)
|
||||||
|
if not msg_.sticker:
|
||||||
|
add_ban_chat_member_job(chat.id, user.id)
|
||||||
|
await log(chat, user, LogAction.FAIL_ERROR)
|
||||||
|
await ServiceMessage.try_delete(user.id, chat.id)
|
||||||
|
else:
|
||||||
|
await cache.delete(key)
|
||||||
|
await log(chat, user, LogAction.ACCEPT)
|
||||||
|
except TimeoutConversationError:
|
||||||
|
await msg.delay_delete(1)
|
||||||
|
add_ban_chat_member_job(chat.id, user.id)
|
||||||
|
await log(chat, user, LogAction.FAIL_TIMEOUT)
|
||||||
|
await ServiceMessage.try_delete(user.id, chat.id)
|
||||||
|
|
||||||
|
|
||||||
@bot.on_chat_member_updated()
|
@bot.on_chat_member_updated()
|
||||||
async def invite(client: Client, chat_member_updated: ChatMemberUpdated):
|
async def invite(client: Client, chat_member_updated: ChatMemberUpdated):
|
||||||
chat = chat_member_updated.chat
|
chat = chat_member_updated.chat
|
||||||
if await cache.get(f"cid:{chat.id}"):
|
|
||||||
return
|
|
||||||
member = chat_member_updated.new_chat_member
|
member = chat_member_updated.new_chat_member
|
||||||
old_member = chat_member_updated.old_chat_member
|
old_member = chat_member_updated.old_chat_member
|
||||||
if not member:
|
if not member:
|
||||||
@ -27,6 +54,17 @@ async def invite(client: Client, chat_member_updated: ChatMemberUpdated):
|
|||||||
return
|
return
|
||||||
user = member.user
|
user = member.user
|
||||||
old_user = old_member.user if old_member else None
|
old_user = old_member.user if old_member else None
|
||||||
|
if user.is_self:
|
||||||
|
if member.status not in {
|
||||||
|
ChatMemberStatus.ADMINISTRATOR,
|
||||||
|
ChatMemberStatus.MEMBER,
|
||||||
|
}:
|
||||||
|
return
|
||||||
|
await log(chat, chat_member_updated.from_user, LogAction.NEW_GROUP)
|
||||||
|
if chat.username:
|
||||||
|
with contextlib.suppress(Exception):
|
||||||
|
await client.send_message(chat.id, MSG_PUBLIC)
|
||||||
|
return
|
||||||
if user.is_verified or user.is_bot or user.is_deleted or user.is_support:
|
if user.is_verified or user.is_bot or user.is_deleted or user.is_support:
|
||||||
return
|
return
|
||||||
if member.status not in {ChatMemberStatus.MEMBER}:
|
if member.status not in {ChatMemberStatus.MEMBER}:
|
||||||
@ -43,13 +81,6 @@ async def invite(client: Client, chat_member_updated: ChatMemberUpdated):
|
|||||||
}
|
}
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
if user.is_self:
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await log(chat, chat_member_updated.from_user, "NEW_GROUP")
|
|
||||||
if chat.username:
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await client.send_message(chat.id, MSG_PUBLIC)
|
|
||||||
return
|
|
||||||
from_user = chat_member_updated.from_user
|
from_user = chat_member_updated.from_user
|
||||||
if from_user and from_user.id == user.id:
|
if from_user and from_user.id == user.id:
|
||||||
from_user = None
|
from_user = None
|
||||||
@ -61,42 +92,8 @@ async def invite(client: Client, chat_member_updated: ChatMemberUpdated):
|
|||||||
and (await bot.get_chat_member(chat.id, from_user.id)).status
|
and (await bot.get_chat_member(chat.id, from_user.id)).status
|
||||||
in {ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER}
|
in {ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER}
|
||||||
):
|
):
|
||||||
try:
|
with contextlib.suppress(Exception):
|
||||||
msg = await client.send_message(chat.id, ADMIN_MSG)
|
msg: "Message" = await client.send_message(chat.id, ADMIN_MSG)
|
||||||
except Exception:
|
await msg.delay_delete()
|
||||||
return
|
return
|
||||||
add_delete_message_job(msg)
|
await start_verify(client, chat, user)
|
||||||
return
|
|
||||||
try:
|
|
||||||
msg = await client.send_message(chat.id, MSG % (user.mention, user.mention))
|
|
||||||
except Exception:
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await log(chat, user, "REQUEST")
|
|
||||||
msg_ = await client.listen(chat.id, filters=filters.user(user.id), timeout=VERIFY_TIME)
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await msg.delete()
|
|
||||||
if not msg_.sticker:
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await bot.ban_chat_member(
|
|
||||||
chat.id, user.id, datetime.now() + timedelta(minutes=5)
|
|
||||||
)
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await log(chat, user, "FAIL_ERROR")
|
|
||||||
await ServiceMessage.try_delete(user.id, chat.id)
|
|
||||||
else:
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await log(chat, user, "ACCEPT")
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await msg_.delete()
|
|
||||||
except TimeoutConversationError:
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await msg.delete()
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await bot.ban_chat_member(
|
|
||||||
chat.id, user.id, datetime.now() + timedelta(minutes=5)
|
|
||||||
)
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await log(chat, user, "FAIL_TIMEOUT")
|
|
||||||
await ServiceMessage.try_delete(user.id, chat.id)
|
|
||||||
|
17
plugins/clean_message.py
Normal file
17
plugins/clean_message.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from cashews import cache
|
||||||
|
from pyrogram import filters
|
||||||
|
|
||||||
|
from sticker import bot
|
||||||
|
from sticker.single_utils import Message
|
||||||
|
|
||||||
|
|
||||||
|
@bot.on_message(filters=filters.group & ~filters.service, group=1)
|
||||||
|
async def clean_message(_, message: "Message"):
|
||||||
|
if not message.from_user:
|
||||||
|
return
|
||||||
|
cid = message.chat.id
|
||||||
|
uid = message.from_user.id
|
||||||
|
key = f"wait:{cid}:{uid}"
|
||||||
|
result = await cache.get(key)
|
||||||
|
if result:
|
||||||
|
await message.delay_delete(1)
|
@ -1,13 +1,12 @@
|
|||||||
import contextlib
|
import contextlib
|
||||||
|
|
||||||
from cashews import cache
|
|
||||||
from pyrogram.types import ChatJoinRequest
|
from pyrogram.types import ChatJoinRequest
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
|
|
||||||
from sticker.languages import MSG, MSG_SUCCESS, MSG_FAILURE, VERIFY_TIME
|
from sticker.languages import MSG, MSG_SUCCESS, MSG_FAILURE, VERIFY_TIME
|
||||||
from sticker.single_utils import Client
|
from sticker.single_utils import Client
|
||||||
from sticker.scheduler import add_decline_request_job, rem_decline_request_job
|
from sticker.scheduler import add_decline_request_job, rem_decline_request_job
|
||||||
from sticker import bot, log
|
from sticker import bot, log, LogAction
|
||||||
|
|
||||||
from pyromod.utils.errors import TimeoutConversationError
|
from pyromod.utils.errors import TimeoutConversationError
|
||||||
|
|
||||||
@ -15,24 +14,24 @@ from pyromod.utils.errors import TimeoutConversationError
|
|||||||
@bot.on_chat_join_request()
|
@bot.on_chat_join_request()
|
||||||
async def new_member(client: Client, chat_join_request: ChatJoinRequest):
|
async def new_member(client: Client, chat_join_request: ChatJoinRequest):
|
||||||
chat = chat_join_request.chat
|
chat = chat_join_request.chat
|
||||||
await cache.set(f"cid:{chat.id}", "True", expire=3600, exist=True)
|
|
||||||
user = chat_join_request.from_user
|
user = chat_join_request.from_user
|
||||||
add_decline_request_job(chat_join_request)
|
add_decline_request_job(chat_join_request)
|
||||||
try:
|
try:
|
||||||
with contextlib.suppress(Exception):
|
await log(chat, user, LogAction.REQUEST)
|
||||||
await log(chat, user, "REQUEST")
|
await client.ask(
|
||||||
await client.ask(user.id, MSG % (chat.title, chat.title), filters=filters.sticker, timeout=VERIFY_TIME)
|
user.id,
|
||||||
|
MSG % (chat.title, chat.title),
|
||||||
|
filters=filters.sticker,
|
||||||
|
timeout=VERIFY_TIME,
|
||||||
|
)
|
||||||
with contextlib.suppress(Exception):
|
with contextlib.suppress(Exception):
|
||||||
await client.send_message(user.id, MSG_SUCCESS)
|
await client.send_message(user.id, MSG_SUCCESS)
|
||||||
await chat_join_request.approve()
|
await chat_join_request.approve()
|
||||||
with contextlib.suppress(Exception):
|
await log(chat, user, LogAction.ACCEPT)
|
||||||
await log(chat, user, "ACCEPT")
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
rem_decline_request_job(chat_join_request)
|
rem_decline_request_job(chat_join_request)
|
||||||
except TimeoutConversationError:
|
except TimeoutConversationError:
|
||||||
with contextlib.suppress(Exception):
|
with contextlib.suppress(Exception):
|
||||||
await client.send_message(user.id, MSG_FAILURE)
|
await client.send_message(user.id, MSG_FAILURE)
|
||||||
with contextlib.suppress(Exception):
|
with contextlib.suppress(Exception):
|
||||||
await chat_join_request.decline()
|
await chat_join_request.decline()
|
||||||
with contextlib.suppress(Exception):
|
await log(chat, user, LogAction.FAIL_TIMEOUT)
|
||||||
await log(chat, user, "FAIL_TIMEOUT")
|
|
||||||
|
@ -1,25 +1,23 @@
|
|||||||
import contextlib
|
from cashews import cache
|
||||||
|
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from pyrogram.enums import ChatMemberStatus
|
from pyrogram.enums import ChatMemberStatus
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
|
|
||||||
from pyromod.utils.errors import TimeoutConversationError
|
from pyromod.utils.errors import TimeoutConversationError
|
||||||
from sticker.languages import RE_MSG, VERIFY_TIME
|
from sticker.languages import RE_MSG, VERIFY_TIME
|
||||||
from sticker.scheduler import add_delete_message_job
|
from sticker.scheduler import add_ban_chat_member_job
|
||||||
from sticker.single_utils import Message, Client
|
from sticker.single_utils import Message, Client
|
||||||
from sticker import bot, log
|
from sticker import bot, log, LogAction
|
||||||
|
|
||||||
|
|
||||||
@bot.on_message(filters=filters.group & filters.command("reverify"))
|
@bot.on_message(filters=filters.group & filters.command("reverify"))
|
||||||
async def re_verify(client: Client, message: Message):
|
async def re_verify(client: Client, message: Message):
|
||||||
if not message.from_user or not message.reply_to_message:
|
reply_to: "Message" = message.reply_to_message
|
||||||
|
if not message.from_user or not reply_to:
|
||||||
msg: Message = await message.reply("请回复一条消息来使 Ta 重新验证。")
|
msg: Message = await message.reply("请回复一条消息来使 Ta 重新验证。")
|
||||||
add_delete_message_job(message, 10)
|
await message.delay_delete(10)
|
||||||
add_delete_message_job(msg, 10)
|
await msg.delay_delete(10)
|
||||||
return
|
return
|
||||||
if not message.reply_to_message.from_user:
|
if not reply_to.from_user:
|
||||||
return
|
return
|
||||||
chat = message.chat
|
chat = message.chat
|
||||||
user = message.from_user
|
user = message.from_user
|
||||||
@ -27,7 +25,7 @@ async def re_verify(client: Client, message: Message):
|
|||||||
if member.status not in [ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR]:
|
if member.status not in [ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR]:
|
||||||
return
|
return
|
||||||
|
|
||||||
user = message.reply_to_message.from_user
|
user = reply_to.from_user
|
||||||
if (
|
if (
|
||||||
user.is_self
|
user.is_self
|
||||||
or user.is_verified
|
or user.is_verified
|
||||||
@ -37,46 +35,36 @@ async def re_verify(client: Client, message: Message):
|
|||||||
):
|
):
|
||||||
return
|
return
|
||||||
member = await client.get_chat_member(chat.id, user.id)
|
member = await client.get_chat_member(chat.id, user.id)
|
||||||
with contextlib.suppress(Exception):
|
await message.delay_delete(1)
|
||||||
await message.delete()
|
key = f"wait:{chat.id}:{user.id}"
|
||||||
|
await cache.set(key, "True", expire=VERIFY_TIME + 5)
|
||||||
try:
|
try:
|
||||||
msg = await message.reply_to_message.reply(RE_MSG % (user.mention, user.mention))
|
msg = await reply_to.reply(RE_MSG % (user.mention, user.mention))
|
||||||
except Exception as _:
|
except Exception as _:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
msg_ = await client.listen(chat.id, filters=filters.user(user.id), timeout=VERIFY_TIME)
|
msg_ = await client.listen(
|
||||||
with contextlib.suppress(Exception):
|
chat.id, filters=filters.user(user.id), timeout=VERIFY_TIME
|
||||||
await msg.delete()
|
)
|
||||||
|
await msg.delay_delete(1)
|
||||||
|
await msg_.delay_delete(1)
|
||||||
if not msg_.sticker:
|
if not msg_.sticker:
|
||||||
with contextlib.suppress(Exception):
|
await reply_to.delay_delete(1)
|
||||||
await message.reply_to_message.delete()
|
|
||||||
if member.status not in [
|
if member.status not in [
|
||||||
ChatMemberStatus.OWNER,
|
ChatMemberStatus.OWNER,
|
||||||
ChatMemberStatus.ADMINISTRATOR,
|
ChatMemberStatus.ADMINISTRATOR,
|
||||||
]:
|
]:
|
||||||
with contextlib.suppress(Exception):
|
add_ban_chat_member_job(chat.id, user.id)
|
||||||
await bot.ban_chat_member(
|
await log(chat, user, LogAction.FAIL_ERROR)
|
||||||
chat.id, user.id, datetime.now() + timedelta(minutes=5)
|
|
||||||
)
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await log(chat, user, "FAIL_ERROR")
|
|
||||||
else:
|
else:
|
||||||
with contextlib.suppress(Exception):
|
await cache.delete(key)
|
||||||
await log(chat, user, "ACCEPT")
|
await log(chat, user, LogAction.ACCEPT)
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await msg_.delete()
|
|
||||||
except TimeoutConversationError:
|
except TimeoutConversationError:
|
||||||
with contextlib.suppress(Exception):
|
await msg.delay_delete(1)
|
||||||
await msg.delete()
|
await reply_to.delay_delete(1)
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await message.reply_to_message.delete()
|
|
||||||
if member.status not in [
|
if member.status not in [
|
||||||
ChatMemberStatus.OWNER,
|
ChatMemberStatus.OWNER,
|
||||||
ChatMemberStatus.ADMINISTRATOR,
|
ChatMemberStatus.ADMINISTRATOR,
|
||||||
]:
|
]:
|
||||||
with contextlib.suppress(Exception):
|
add_ban_chat_member_job(chat.id, user.id)
|
||||||
await bot.ban_chat_member(
|
await log(chat, user, LogAction.FAIL_TIMEOUT)
|
||||||
chat.id, user.id, datetime.now() + timedelta(minutes=5)
|
|
||||||
)
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
await log(chat, user, "FAIL_TIMEOUT")
|
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
"""
|
|
||||||
pyromod - A monkeypatcher add-on for Pyrogram
|
|
||||||
Copyright (C) 2020 Cezar H. <https://github.com/usernein>
|
|
||||||
|
|
||||||
This file is part of pyromod.
|
|
||||||
|
|
||||||
pyromod is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
pyromod is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with pyromod. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .filters import dice
|
|
@ -1,28 +0,0 @@
|
|||||||
"""
|
|
||||||
pyromod - A monkeypatcher add-on for Pyrogram
|
|
||||||
Copyright (C) 2020 Cezar H. <https://github.com/usernein>
|
|
||||||
|
|
||||||
This file is part of pyromod.
|
|
||||||
|
|
||||||
pyromod is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
pyromod is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with pyromod. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import pyrogram
|
|
||||||
|
|
||||||
|
|
||||||
def dice(ctx, message):
|
|
||||||
return hasattr(message, "dice") and message.dice
|
|
||||||
|
|
||||||
|
|
||||||
pyrogram.filters.dice = dice
|
|
@ -1,20 +0,0 @@
|
|||||||
"""
|
|
||||||
pyromod - A monkeypatcher add-on for Pyrogram
|
|
||||||
Copyright (C) 2020 Cezar H. <https://github.com/usernein>
|
|
||||||
|
|
||||||
This file is part of pyromod.
|
|
||||||
|
|
||||||
pyromod is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
pyromod is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with pyromod. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
from .helpers import ikb, bki, ntb, btn, kb, kbtn, array_chunk, force_reply
|
|
@ -1,86 +0,0 @@
|
|||||||
from pyrogram.types import (
|
|
||||||
InlineKeyboardButton,
|
|
||||||
InlineKeyboardMarkup,
|
|
||||||
KeyboardButton,
|
|
||||||
ReplyKeyboardMarkup,
|
|
||||||
ForceReply,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def ikb(rows=None):
|
|
||||||
if rows is None:
|
|
||||||
rows = []
|
|
||||||
lines = []
|
|
||||||
for row in rows:
|
|
||||||
line = []
|
|
||||||
for button in row:
|
|
||||||
button = btn(*button) # InlineKeyboardButton
|
|
||||||
line.append(button)
|
|
||||||
lines.append(line)
|
|
||||||
return InlineKeyboardMarkup(inline_keyboard=lines)
|
|
||||||
# return {'inline_keyboard': lines}
|
|
||||||
|
|
||||||
|
|
||||||
def btn(text, value, type="callback_data"):
|
|
||||||
return InlineKeyboardButton(text, **{type: value})
|
|
||||||
# return {'text': text, type: value}
|
|
||||||
|
|
||||||
|
|
||||||
# The inverse of above
|
|
||||||
def bki(keyboard):
|
|
||||||
lines = []
|
|
||||||
for row in keyboard.inline_keyboard:
|
|
||||||
line = []
|
|
||||||
for button in row:
|
|
||||||
button = ntb(button) # btn() format
|
|
||||||
line.append(button)
|
|
||||||
lines.append(line)
|
|
||||||
return lines
|
|
||||||
# return ikb() format
|
|
||||||
|
|
||||||
|
|
||||||
def ntb(button):
|
|
||||||
for btn_type in [
|
|
||||||
"callback_data",
|
|
||||||
"url",
|
|
||||||
"switch_inline_query",
|
|
||||||
"switch_inline_query_current_chat",
|
|
||||||
"callback_game",
|
|
||||||
]:
|
|
||||||
value = getattr(button, btn_type)
|
|
||||||
if value:
|
|
||||||
break
|
|
||||||
button = [button.text, value]
|
|
||||||
if btn_type != "callback_data":
|
|
||||||
button.append(btn_type)
|
|
||||||
return button
|
|
||||||
# return {'text': text, type: value}
|
|
||||||
|
|
||||||
|
|
||||||
def kb(rows=None, **kwargs):
|
|
||||||
if rows is None:
|
|
||||||
rows = []
|
|
||||||
lines = []
|
|
||||||
for row in rows:
|
|
||||||
line = []
|
|
||||||
for button in row:
|
|
||||||
button_type = type(button)
|
|
||||||
if button_type == str:
|
|
||||||
button = KeyboardButton(button)
|
|
||||||
elif button_type == dict:
|
|
||||||
button = KeyboardButton(**button)
|
|
||||||
|
|
||||||
line.append(button)
|
|
||||||
lines.append(line)
|
|
||||||
return ReplyKeyboardMarkup(keyboard=lines, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
kbtn = KeyboardButton
|
|
||||||
|
|
||||||
|
|
||||||
def force_reply(selective=True):
|
|
||||||
return ForceReply(selective=selective)
|
|
||||||
|
|
||||||
|
|
||||||
def array_chunk(input_, size):
|
|
||||||
return [input_[i : i + size] for i in range(0, len(input_), size)]
|
|
@ -19,16 +19,18 @@ along with pyromod. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import contextlib
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
|
|
||||||
from typing import Dict
|
|
||||||
from sticker.scheduler import add_delete_message_job
|
from sticker.scheduler import add_delete_message_job
|
||||||
from ..utils import patch, patchable
|
from ..utils import patch, patchable
|
||||||
from ..utils.errors import ListenerCanceled, TimeoutConversationError
|
from ..utils.errors import ListenerCanceled, TimeoutConversationError
|
||||||
|
|
||||||
pyrogram.errors.ListenerCanceled = ListenerCanceled
|
pyrogram.errors.ListenerCanceled = ListenerCanceled
|
||||||
|
LOCK = asyncio.Lock()
|
||||||
|
DONE = []
|
||||||
|
|
||||||
|
|
||||||
@patch(pyrogram.client.Client)
|
@patch(pyrogram.client.Client)
|
||||||
@ -63,6 +65,7 @@ class Client:
|
|||||||
|
|
||||||
@patchable
|
@patchable
|
||||||
def clear_listener(self, chat_id, future):
|
def clear_listener(self, chat_id, future):
|
||||||
|
with contextlib.suppress(KeyError):
|
||||||
if future == self.listening[chat_id]["future"]:
|
if future == self.listening[chat_id]["future"]:
|
||||||
self.listening.pop(chat_id, None)
|
self.listening.pop(chat_id, None)
|
||||||
|
|
||||||
@ -90,25 +93,33 @@ class MessageHandler:
|
|||||||
|
|
||||||
@patchable
|
@patchable
|
||||||
async def resolve_listener(self, client, message, *args):
|
async def resolve_listener(self, client, message, *args):
|
||||||
|
global LOCK, DONE
|
||||||
|
async with LOCK:
|
||||||
listener = client.listening.get(message.chat.id)
|
listener = client.listening.get(message.chat.id)
|
||||||
|
if listener:
|
||||||
|
with contextlib.suppress(ValueError):
|
||||||
|
DONE.remove(listener)
|
||||||
if listener and not listener["future"].done():
|
if listener and not listener["future"].done():
|
||||||
listener["future"].set_result(message)
|
listener["future"].set_result(message)
|
||||||
else:
|
return
|
||||||
if listener and listener["future"].done():
|
if listener and listener["future"].done():
|
||||||
client.clear_listener(message.chat.id, listener["future"])
|
client.clear_listener(message.chat.id, listener["future"])
|
||||||
await self.user_callback(client, message, *args)
|
await self.user_callback(client, message, *args)
|
||||||
|
|
||||||
@patchable
|
@patchable
|
||||||
async def check(self, client, update):
|
async def check(self, client, update):
|
||||||
|
global LOCK, DONE
|
||||||
|
async with LOCK:
|
||||||
listener = client.listening.get(update.chat.id)
|
listener = client.listening.get(update.chat.id)
|
||||||
|
if listener and (listener not in DONE) and (not listener["future"].done()):
|
||||||
if listener and not listener["future"].done():
|
if callable(listener["filters"]):
|
||||||
return (
|
result = await listener["filters"](client, update)
|
||||||
await listener["filters"](client, update)
|
if result:
|
||||||
if callable(listener["filters"])
|
DONE.append(listener)
|
||||||
else True
|
return result
|
||||||
)
|
else:
|
||||||
|
DONE.append(listener)
|
||||||
|
return True
|
||||||
return await self.filters(client, update) if callable(self.filters) else True
|
return await self.filters(client, update) if callable(self.filters) else True
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
"""
|
|
||||||
pyromod - A monkeypatcher add-on for Pyrogram
|
|
||||||
Copyright (C) 2020 Cezar H. <https://github.com/usernein>
|
|
||||||
|
|
||||||
This file is part of pyromod.
|
|
||||||
|
|
||||||
pyromod is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
pyromod is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with pyromod. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
from .pagination import Pagination
|
|
@ -1,93 +0,0 @@
|
|||||||
"""
|
|
||||||
pyromod - A monkeypatcher add-on for Pyrogram
|
|
||||||
Copyright (C) 2020 Cezar H. <https://github.com/usernein>
|
|
||||||
|
|
||||||
This file is part of pyromod.
|
|
||||||
|
|
||||||
pyromod is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
pyromod is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with pyromod. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
import math
|
|
||||||
from ..helpers import array_chunk
|
|
||||||
|
|
||||||
|
|
||||||
class Pagination:
|
|
||||||
def __init__(self, objects, page_data=None, item_data=None, item_title=None):
|
|
||||||
default_page_callback = lambda x: str(x)
|
|
||||||
default_item_callback = lambda i, pg: f"[{pg}] {i}"
|
|
||||||
self.objects = objects
|
|
||||||
self.page_data = page_data or default_page_callback
|
|
||||||
self.item_data = item_data or default_item_callback
|
|
||||||
self.item_title = item_title or default_item_callback
|
|
||||||
|
|
||||||
def create(self, page, lines=5, columns=1):
|
|
||||||
quant_per_page = lines * columns
|
|
||||||
page = 1 if page <= 0 else page
|
|
||||||
offset = (page - 1) * quant_per_page
|
|
||||||
stop = offset + quant_per_page
|
|
||||||
cutted = self.objects[offset:stop]
|
|
||||||
|
|
||||||
total = len(self.objects)
|
|
||||||
pages_range = [
|
|
||||||
*range(1, math.ceil(total / quant_per_page) + 1)
|
|
||||||
] # each item is a page
|
|
||||||
last_page = len(pages_range)
|
|
||||||
|
|
||||||
nav = []
|
|
||||||
if page <= 3:
|
|
||||||
for n in [1, 2, 3]:
|
|
||||||
if n not in pages_range:
|
|
||||||
continue
|
|
||||||
text = f"· {n} ·" if n == page else n
|
|
||||||
nav.append((text, self.page_data(n)))
|
|
||||||
if last_page >= 4:
|
|
||||||
nav.append(("4 ›" if last_page > 5 else 4, self.page_data(4)))
|
|
||||||
if last_page > 4:
|
|
||||||
nav.append(
|
|
||||||
(
|
|
||||||
f"{last_page} »" if last_page > 5 else last_page,
|
|
||||||
self.page_data(last_page),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
elif page >= last_page - 2:
|
|
||||||
nav.extend(
|
|
||||||
[
|
|
||||||
("« 1" if last_page > 5 else 1, self.page_data(1)),
|
|
||||||
(
|
|
||||||
f"‹ {last_page - 3}" if last_page > 5 else last_page - 3,
|
|
||||||
self.page_data(last_page - 3),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
for n in range(last_page - 2, last_page + 1):
|
|
||||||
text = f"· {n} ·" if n == page else n
|
|
||||||
nav.append((text, self.page_data(n)))
|
|
||||||
else:
|
|
||||||
nav = [
|
|
||||||
("« 1", self.page_data(1)),
|
|
||||||
(f"‹ {page - 1}", self.page_data(page - 1)),
|
|
||||||
(f"· {page} ·", "noop"),
|
|
||||||
(f"{page + 1} ›", self.page_data(page + 1)),
|
|
||||||
(f"{last_page} »", self.page_data(last_page)),
|
|
||||||
]
|
|
||||||
|
|
||||||
buttons = [
|
|
||||||
(self.item_title(item, page), self.item_data(item, page)) for item in cutted
|
|
||||||
]
|
|
||||||
|
|
||||||
kb_lines = array_chunk(buttons, columns)
|
|
||||||
if last_page > 1:
|
|
||||||
kb_lines.append(nav)
|
|
||||||
|
|
||||||
return kb_lines
|
|
@ -1,5 +1,7 @@
|
|||||||
import contextlib
|
import contextlib
|
||||||
import sys
|
import sys
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
from cashews import cache
|
from cashews import cache
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from logging import getLogger, StreamHandler, CRITICAL, INFO, basicConfig, DEBUG
|
from logging import getLogger, StreamHandler, CRITICAL, INFO, basicConfig, DEBUG
|
||||||
@ -54,22 +56,48 @@ bot = Client(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def log(chat, user, action):
|
class LogAction(str, Enum):
|
||||||
|
FAIL_ERROR = "FAIL_ERROR"
|
||||||
|
FAIL_TIMEOUT = "FAIL_TIMEOUT"
|
||||||
|
ACCEPT = "ACCEPT"
|
||||||
|
NEW_GROUP = "NEW_GROUP"
|
||||||
|
REQUEST = "REQUEST"
|
||||||
|
|
||||||
|
|
||||||
|
async def log(chat, user, action: LogAction):
|
||||||
|
scheduler.add_job(
|
||||||
|
_log,
|
||||||
|
args=[chat, user, action],
|
||||||
|
replace_existing=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def _log(chat, user, action: LogAction):
|
||||||
if not Config.LOG_CHANNEL:
|
if not Config.LOG_CHANNEL:
|
||||||
return
|
return
|
||||||
me = await bot.get_me()
|
me = await bot.get_me()
|
||||||
event = {
|
event = {
|
||||||
"FAIL_ERROR": "回答错误",
|
LogAction.FAIL_ERROR: "回答错误",
|
||||||
"FAIL_TIMEOUT": "回答超时",
|
LogAction.FAIL_TIMEOUT: "回答超时",
|
||||||
"ACCEPT": "通过验证",
|
LogAction.ACCEPT: "通过验证",
|
||||||
"NEW_GROUP": "加入群组",
|
LogAction.NEW_GROUP: "加入群组",
|
||||||
"REQUEST": "发起验证",
|
LogAction.REQUEST: "发起验证",
|
||||||
}
|
}
|
||||||
msg = """#%s
|
msg = """#%s
|
||||||
群组: %s
|
群组: %s
|
||||||
群组id: <code>%s</code>
|
群组id: <code>%s</code>
|
||||||
用户: #id%s
|
用户: #id%s
|
||||||
|
昵称:<code>%s</code>
|
||||||
OPBot: #bot%s
|
OPBot: #bot%s
|
||||||
事件: %s"""
|
事件: %s"""
|
||||||
msg %= (action, chat.title, chat.id, user.id if user else "", me.id, event[action])
|
user_name = user.full_name if user else ""
|
||||||
|
msg %= (
|
||||||
|
action.value,
|
||||||
|
chat.title,
|
||||||
|
chat.id,
|
||||||
|
user.id if user else "",
|
||||||
|
user_name,
|
||||||
|
me.id,
|
||||||
|
event[action],
|
||||||
|
)
|
||||||
await bot.send_message(Config.LOG_CHANNEL, msg)
|
await bot.send_message(Config.LOG_CHANNEL, msg)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
VERIFY_TIME = 60
|
VERIFY_TIME = 180
|
||||||
MSG_PUBLIC = """您好,我发现此群组为公开群组,您需要联系创建者打开 `管理员批准后才能入群` 功能,我才能更好地工作。"""
|
MSG_PUBLIC = """您好,我发现此群组为公开群组,您需要联系创建者打开 `管理员批准后才能入群` 功能,我才能更好地工作。"""
|
||||||
MSG_SUCCESS = """验证成功,您已经成为群组的一员了!
|
MSG_SUCCESS = """验证成功,您已经成为群组的一员了!
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import pytz
|
|||||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||||
from pyrogram.types import ChatJoinRequest
|
from pyrogram.types import ChatJoinRequest
|
||||||
|
|
||||||
|
from sticker.languages import VERIFY_TIME
|
||||||
from sticker.single_utils import Message
|
from sticker.single_utils import Message
|
||||||
|
|
||||||
scheduler = AsyncIOScheduler(timezone="Asia/ShangHai")
|
scheduler = AsyncIOScheduler(timezone="Asia/ShangHai")
|
||||||
@ -24,6 +25,17 @@ async def decline_request(chat_join_request: ChatJoinRequest):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
async def ban_chat_member(chat_id: int, user_id: int):
|
||||||
|
from sticker import bot
|
||||||
|
|
||||||
|
with contextlib.suppress(Exception):
|
||||||
|
await bot.ban_chat_member(
|
||||||
|
chat_id, user_id, datetime.datetime.now() + datetime.timedelta(minutes=5)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def add_delete_message_job(message: Message, delete_seconds: int = 60):
|
def add_delete_message_job(message: Message, delete_seconds: int = 60):
|
||||||
scheduler.add_job(
|
scheduler.add_job(
|
||||||
delete_message,
|
delete_message,
|
||||||
@ -45,7 +57,17 @@ def add_decline_request_job(chat_join_request: ChatJoinRequest):
|
|||||||
name=f"{chat_join_request.chat.id}|{chat_join_request.from_user.id}|decline_request",
|
name=f"{chat_join_request.chat.id}|{chat_join_request.from_user.id}|decline_request",
|
||||||
args=[chat_join_request],
|
args=[chat_join_request],
|
||||||
run_date=datetime.datetime.now(pytz.timezone("Asia/Shanghai"))
|
run_date=datetime.datetime.now(pytz.timezone("Asia/Shanghai"))
|
||||||
+ datetime.timedelta(seconds=60),
|
+ datetime.timedelta(seconds=VERIFY_TIME),
|
||||||
|
replace_existing=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def add_ban_chat_member_job(chat_id: int, user_id: int):
|
||||||
|
scheduler.add_job(
|
||||||
|
ban_chat_member,
|
||||||
|
id=f"{chat_id}|{user_id}|ban_chat_member",
|
||||||
|
name=f"{chat_id}|{user_id}|ban_chat_member",
|
||||||
|
args=[chat_id, user_id],
|
||||||
replace_existing=True,
|
replace_existing=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user