mirror of
https://github.com/Xtao-Labs/sticker-captcha-bot.git
synced 2024-11-21 22:58:08 +00:00
fix: a bug
This commit is contained in:
parent
4ff489cf95
commit
060aa7b8fa
@ -24,15 +24,6 @@ ADMIN_MSG = """管理员邀请,自动放行。"""
|
||||
async def invite(client: Client, chat_member_updated: ChatMemberUpdated):
|
||||
chat = chat_member_updated.chat
|
||||
old_chat_member = chat_member_updated.old_chat_member
|
||||
if user := chat_member_updated.new_chat_member and not old_chat_member:
|
||||
if not user.user:
|
||||
return
|
||||
if user.user.is_self:
|
||||
with contextlib.suppress(Exception):
|
||||
await log(chat, user.invited_by, "NEW_GROUP")
|
||||
if chat.username:
|
||||
with contextlib.suppress(Exception):
|
||||
await client.send_message(chat.id, MSG_PUBLIC)
|
||||
if await cache.get(f"cid:{chat.id}"):
|
||||
return
|
||||
member = chat_member_updated.new_chat_member
|
||||
@ -43,20 +34,38 @@ async def invite(client: Client, chat_member_updated: ChatMemberUpdated):
|
||||
return
|
||||
user = member.user
|
||||
old_user = old_member.user if old_member else None
|
||||
if user.is_self or 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
|
||||
if member.status not in {ChatMemberStatus.MEMBER}:
|
||||
return
|
||||
if old_user and old_user.id == user.id and old_user.status in {
|
||||
if (
|
||||
old_user
|
||||
and old_user.id == user.id
|
||||
and old_user.status
|
||||
in {
|
||||
ChatMemberStatus.ADMINISTRATOR,
|
||||
ChatMemberStatus.OWNER,
|
||||
ChatMemberStatus.MEMBER,
|
||||
ChatMemberStatus.RESTRICTED,
|
||||
}:
|
||||
}
|
||||
):
|
||||
return
|
||||
if user and chat_member_updated.from_user and (
|
||||
await bot.get_chat_member(chat.id, chat_member_updated.from_user.id)
|
||||
).status in {ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER}:
|
||||
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
|
||||
if from_user and from_user.id == user.id:
|
||||
from_user = None
|
||||
if (
|
||||
user
|
||||
and from_user
|
||||
and (await bot.get_chat_member(chat.id, from_user.id)).status
|
||||
in {ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER}
|
||||
):
|
||||
try:
|
||||
msg = await client.send_message(chat.id, ADMIN_MSG)
|
||||
except Exception:
|
||||
@ -75,7 +84,9 @@ async def invite(client: Client, chat_member_updated: ChatMemberUpdated):
|
||||
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))
|
||||
await bot.ban_chat_member(
|
||||
chat.id, user.id, datetime.now() + timedelta(minutes=5)
|
||||
)
|
||||
with contextlib.suppress(Exception):
|
||||
await log(chat, user, "FAIL_ERROR")
|
||||
else:
|
||||
@ -87,6 +98,8 @@ async def invite(client: Client, chat_member_updated: ChatMemberUpdated):
|
||||
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))
|
||||
await bot.ban_chat_member(
|
||||
chat.id, user.id, datetime.now() + timedelta(minutes=5)
|
||||
)
|
||||
with contextlib.suppress(Exception):
|
||||
await log(chat, user, "FAIL_TIMEOUT")
|
||||
|
@ -31,7 +31,13 @@ async def re_verify(client: Client, message: Message):
|
||||
return
|
||||
|
||||
user = message.reply_to_message.from_user
|
||||
if user.is_self or user.is_verified or user.is_bot or user.is_deleted or user.is_support:
|
||||
if (
|
||||
user.is_self
|
||||
or user.is_verified
|
||||
or user.is_bot
|
||||
or user.is_deleted
|
||||
or user.is_support
|
||||
):
|
||||
return
|
||||
member = await client.get_chat_member(chat.id, user.id)
|
||||
with contextlib.suppress(Exception):
|
||||
@ -47,9 +53,14 @@ async def re_verify(client: Client, message: Message):
|
||||
if not msg_.sticker:
|
||||
with contextlib.suppress(Exception):
|
||||
await message.reply_to_message.delete()
|
||||
if member.status not in [ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR]:
|
||||
if member.status not in [
|
||||
ChatMemberStatus.OWNER,
|
||||
ChatMemberStatus.ADMINISTRATOR,
|
||||
]:
|
||||
with contextlib.suppress(Exception):
|
||||
await bot.ban_chat_member(chat.id, user.id, datetime.now() + timedelta(minutes=5))
|
||||
await bot.ban_chat_member(
|
||||
chat.id, user.id, datetime.now() + timedelta(minutes=5)
|
||||
)
|
||||
with contextlib.suppress(Exception):
|
||||
await log(chat, user, "FAIL_ERROR")
|
||||
else:
|
||||
@ -62,8 +73,13 @@ async def re_verify(client: Client, message: Message):
|
||||
await msg.delete()
|
||||
with contextlib.suppress(Exception):
|
||||
await message.reply_to_message.delete()
|
||||
if member.status not in [ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR]:
|
||||
if member.status not in [
|
||||
ChatMemberStatus.OWNER,
|
||||
ChatMemberStatus.ADMINISTRATOR,
|
||||
]:
|
||||
with contextlib.suppress(Exception):
|
||||
await bot.ban_chat_member(chat.id, user.id, datetime.now() + timedelta(minutes=5))
|
||||
await bot.ban_chat_member(
|
||||
chat.id, user.id, datetime.now() + timedelta(minutes=5)
|
||||
)
|
||||
with contextlib.suppress(Exception):
|
||||
await log(chat, user, "FAIL_TIMEOUT")
|
||||
|
@ -15,10 +15,17 @@ async def start(client: Client, message: Message):
|
||||
quote=True,
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[
|
||||
[InlineKeyboardButton(
|
||||
"Github",
|
||||
url="https://github.com/Xtao-Labs/sticker-captcha-bot")],
|
||||
[InlineKeyboardButton(
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"Github", url="https://github.com/Xtao-Labs/sticker-captcha-bot"
|
||||
)
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"邀请入群",
|
||||
url=f"https://t.me/{me.username}?startgroup=start&admin=can_invite_users")]
|
||||
]))
|
||||
url=f"https://t.me/{me.username}?startgroup=start&admin=can_invite_users",
|
||||
)
|
||||
],
|
||||
]
|
||||
),
|
||||
)
|
||||
|
@ -22,7 +22,7 @@ import pyrogram
|
||||
|
||||
|
||||
def dice(ctx, message):
|
||||
return hasattr(message, 'dice') and message.dice
|
||||
return hasattr(message, "dice") and message.dice
|
||||
|
||||
|
||||
pyrogram.filters.dice = dice
|
||||
|
@ -1,4 +1,10 @@
|
||||
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ForceReply
|
||||
from pyrogram.types import (
|
||||
InlineKeyboardButton,
|
||||
InlineKeyboardMarkup,
|
||||
KeyboardButton,
|
||||
ReplyKeyboardMarkup,
|
||||
ForceReply,
|
||||
)
|
||||
|
||||
|
||||
def ikb(rows=None):
|
||||
@ -15,7 +21,7 @@ def ikb(rows=None):
|
||||
# return {'inline_keyboard': lines}
|
||||
|
||||
|
||||
def btn(text, value, type='callback_data'):
|
||||
def btn(text, value, type="callback_data"):
|
||||
return InlineKeyboardButton(text, **{type: value})
|
||||
# return {'text': text, type: value}
|
||||
|
||||
@ -34,13 +40,18 @@ def bki(keyboard):
|
||||
|
||||
|
||||
def ntb(button):
|
||||
for btn_type in ['callback_data', 'url', 'switch_inline_query', 'switch_inline_query_current_chat',
|
||||
'callback_game']:
|
||||
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':
|
||||
if btn_type != "callback_data":
|
||||
button.append(btn_type)
|
||||
return button
|
||||
# return {'text': text, type: value}
|
||||
@ -72,4 +83,4 @@ def force_reply(selective=True):
|
||||
|
||||
|
||||
def array_chunk(input_, size):
|
||||
return [input_[i:i + size] for i in range(0, len(input_), size)]
|
||||
return [input_[i : i + size] for i in range(0, len(input_), size)]
|
||||
|
@ -47,12 +47,8 @@ class Client:
|
||||
chat_id = chat.id
|
||||
|
||||
future = self.loop.create_future()
|
||||
future.add_done_callback(
|
||||
functools.partial(self.clear_listener, chat_id)
|
||||
)
|
||||
self.listening.update({
|
||||
chat_id: {"future": future, "filters": filters}
|
||||
})
|
||||
future.add_done_callback(functools.partial(self.clear_listener, chat_id))
|
||||
self.listening.update({chat_id: {"future": future, "filters": filters}})
|
||||
try:
|
||||
return await asyncio.wait_for(future, timeout)
|
||||
except asyncio.exceptions.TimeoutError as e:
|
||||
@ -73,11 +69,11 @@ class Client:
|
||||
@patchable
|
||||
def cancel_listener(self, chat_id):
|
||||
listener = self.listening.get(chat_id)
|
||||
if not listener or listener['future'].done():
|
||||
if not listener or listener["future"].done():
|
||||
return
|
||||
|
||||
listener['future'].set_exception(ListenerCanceled())
|
||||
self.clear_listener(chat_id, listener['future'])
|
||||
listener["future"].set_exception(ListenerCanceled())
|
||||
self.clear_listener(chat_id, listener["future"])
|
||||
|
||||
@patchable
|
||||
def cancel_all_listener(self):
|
||||
@ -95,26 +91,26 @@ class MessageHandler:
|
||||
@patchable
|
||||
async def resolve_listener(self, client, message, *args):
|
||||
listener = client.listening.get(message.chat.id)
|
||||
if listener and not listener['future'].done():
|
||||
listener['future'].set_result(message)
|
||||
if listener and not listener["future"].done():
|
||||
listener["future"].set_result(message)
|
||||
else:
|
||||
if listener and listener['future'].done():
|
||||
client.clear_listener(message.chat.id, listener['future'])
|
||||
if listener and listener["future"].done():
|
||||
client.clear_listener(message.chat.id, listener["future"])
|
||||
await self.user_callback(client, message, *args)
|
||||
|
||||
@patchable
|
||||
async def check(self, client, update):
|
||||
listener = client.listening.get(update.chat.id)
|
||||
|
||||
if listener and not listener['future'].done():
|
||||
return await listener['filters'](client, update) if callable(listener['filters']) else True
|
||||
|
||||
if listener and not listener["future"].done():
|
||||
return (
|
||||
await self.filters(client, update)
|
||||
if callable(self.filters)
|
||||
await listener["filters"](client, update)
|
||||
if callable(listener["filters"])
|
||||
else True
|
||||
)
|
||||
|
||||
return await self.filters(client, update) if callable(self.filters) else True
|
||||
|
||||
|
||||
@patch(pyrogram.types.user_and_chats.chat.Chat)
|
||||
class Chat(pyrogram.types.Chat):
|
||||
@ -152,9 +148,7 @@ class Message(pyrogram.types.Message):
|
||||
async def safe_delete(self, revoke: bool = True):
|
||||
try:
|
||||
return await self._client.delete_messages(
|
||||
chat_id=self.chat.id,
|
||||
message_ids=self.id,
|
||||
revoke=revoke
|
||||
chat_id=self.chat.id, message_ids=self.id, revoke=revoke
|
||||
)
|
||||
except Exception as e: # noqa
|
||||
return False
|
||||
|
@ -23,8 +23,8 @@ 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}')
|
||||
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
|
||||
@ -38,7 +38,9 @@ class Pagination:
|
||||
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
|
||||
pages_range = [
|
||||
*range(1, math.ceil(total / quant_per_page) + 1)
|
||||
] # each item is a page
|
||||
last_page = len(pages_range)
|
||||
|
||||
nav = []
|
||||
@ -49,19 +51,20 @@ class Pagination:
|
||||
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))
|
||||
)
|
||||
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))
|
||||
(
|
||||
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)),
|
||||
("« 1" if last_page > 5 else 1, self.page_data(1)),
|
||||
(
|
||||
f'‹ {last_page - 3}' if last_page > 5 else last_page - 3,
|
||||
f"‹ {last_page - 3}" if last_page > 5 else last_page - 3,
|
||||
self.page_data(last_page - 3),
|
||||
),
|
||||
]
|
||||
@ -72,16 +75,15 @@ class Pagination:
|
||||
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)),
|
||||
("« 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
|
||||
(self.item_title(item, page), self.item_data(item, page)) for item in cutted
|
||||
]
|
||||
|
||||
kb_lines = array_chunk(buttons, columns)
|
||||
|
@ -2,10 +2,9 @@ class TimeoutConversationError(Exception):
|
||||
"""
|
||||
Occurs when the conversation times out.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
"Response read timed out"
|
||||
)
|
||||
super().__init__("Response read timed out")
|
||||
|
||||
|
||||
class ListenerCanceled(Exception):
|
||||
@ -14,6 +13,4 @@ class ListenerCanceled(Exception):
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
"Listener was canceled"
|
||||
)
|
||||
super().__init__("Listener was canceled")
|
||||
|
@ -21,12 +21,12 @@ along with pyromod. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
def patch(obj):
|
||||
def is_patchable(item):
|
||||
return getattr(item[1], 'patchable', False)
|
||||
return getattr(item[1], "patchable", False)
|
||||
|
||||
def wrapper(container):
|
||||
for name, func in filter(is_patchable, container.__dict__.items()):
|
||||
old = getattr(obj, name, None)
|
||||
setattr(obj, f'old{name}', old)
|
||||
setattr(obj, f"old{name}", old)
|
||||
setattr(obj, name, func)
|
||||
return container
|
||||
|
||||
|
@ -37,26 +37,34 @@ start_time = datetime.now(timezone.utc)
|
||||
|
||||
with contextlib.suppress(ImportError):
|
||||
import uvloop # noqa
|
||||
|
||||
uvloop.install()
|
||||
|
||||
if not scheduler.running:
|
||||
scheduler.start()
|
||||
bot = Client("sticker",
|
||||
bot = Client(
|
||||
"sticker",
|
||||
bot_token=Config.BOT_TOKEN,
|
||||
session_string=Config.STRING_SESSION,
|
||||
api_id=Config.API_ID,
|
||||
api_hash=Config.API_HASH,
|
||||
ipv6=Config.IPV6,
|
||||
proxy=Config.PROXY,
|
||||
plugins={"root": "plugins"})
|
||||
plugins={"root": "plugins"},
|
||||
)
|
||||
|
||||
|
||||
async def log(chat, user, action):
|
||||
if not Config.LOG_CHANNEL:
|
||||
return
|
||||
me = await bot.get_me()
|
||||
event = {"FAIL_ERROR": "回答错误", "FAIL_TIMEOUT": "回答超时", "ACCEPT": "通过验证", "NEW_GROUP": "加入群组",
|
||||
"REQUEST": "发起验证"}
|
||||
event = {
|
||||
"FAIL_ERROR": "回答错误",
|
||||
"FAIL_TIMEOUT": "回答超时",
|
||||
"ACCEPT": "通过验证",
|
||||
"NEW_GROUP": "加入群组",
|
||||
"REQUEST": "发起验证",
|
||||
}
|
||||
msg = """#%s
|
||||
群组: %s
|
||||
群组id: <code>%s</code>
|
||||
|
@ -9,4 +9,5 @@ async def main():
|
||||
await idle()
|
||||
await bot.stop()
|
||||
|
||||
|
||||
bot.run(main())
|
||||
|
@ -13,9 +13,9 @@ def strtobool(val):
|
||||
'val' is anything else.
|
||||
"""
|
||||
val = val.lower()
|
||||
if val in ('y', 'yes', 't', 'true', 'on', '1'):
|
||||
if val in ("y", "yes", "t", "true", "on", "1"):
|
||||
return 1
|
||||
elif val in ('n', 'no', 'f', 'false', 'off', '0'):
|
||||
elif val in ("n", "no", "f", "false", "off", "0"):
|
||||
return 0
|
||||
else:
|
||||
raise ValueError("invalid truth value %r" % (val,))
|
||||
@ -24,7 +24,9 @@ def strtobool(val):
|
||||
try:
|
||||
config = load(open(r"config.yml"), Loader=FullLoader)
|
||||
except FileNotFoundError:
|
||||
print("The configuration file does not exist, and a new configuration file is being generated.")
|
||||
print(
|
||||
"The configuration file does not exist, and a new configuration file is being generated."
|
||||
)
|
||||
copyfile(f"{os.getcwd()}{os.sep}config.gen.yml", "config.yml")
|
||||
sys.exit(1)
|
||||
|
||||
|
@ -26,24 +26,32 @@ async def decline_request(chat_join_request: ChatJoinRequest):
|
||||
|
||||
def add_delete_message_job(message: Message, delete_seconds: int = 60):
|
||||
scheduler.add_job(
|
||||
delete_message, "date",
|
||||
delete_message,
|
||||
"date",
|
||||
id=f"{message.chat.id}|{message.id}|delete_message",
|
||||
name=f"{message.chat.id}|{message.id}|delete_message",
|
||||
args=[message],
|
||||
run_date=datetime.datetime.now(pytz.timezone("Asia/Shanghai")) + datetime.timedelta(seconds=delete_seconds),
|
||||
replace_existing=True)
|
||||
run_date=datetime.datetime.now(pytz.timezone("Asia/Shanghai"))
|
||||
+ datetime.timedelta(seconds=delete_seconds),
|
||||
replace_existing=True,
|
||||
)
|
||||
|
||||
|
||||
def add_decline_request_job(chat_join_request: ChatJoinRequest):
|
||||
scheduler.add_job(
|
||||
decline_request, "date",
|
||||
decline_request,
|
||||
"date",
|
||||
id=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],
|
||||
run_date=datetime.datetime.now(pytz.timezone("Asia/Shanghai")) + datetime.timedelta(seconds=60),
|
||||
replace_existing=True)
|
||||
run_date=datetime.datetime.now(pytz.timezone("Asia/Shanghai"))
|
||||
+ datetime.timedelta(seconds=60),
|
||||
replace_existing=True,
|
||||
)
|
||||
|
||||
|
||||
def rem_decline_request_job(chat_join_request: ChatJoinRequest):
|
||||
if job := scheduler.get_job(f"{chat_join_request.chat.id}|{chat_join_request.from_user.id}|decline_request"):
|
||||
if job := scheduler.get_job(
|
||||
f"{chat_join_request.chat.id}|{chat_join_request.from_user.id}|decline_request"
|
||||
):
|
||||
job.remove()
|
||||
|
@ -25,11 +25,13 @@ class Client(Client): # noqa
|
||||
async def listen(self, chat_id, filters=None, timeout=None) -> Optional[Message]:
|
||||
return
|
||||
|
||||
async def ask(self, chat_id, text, filters=None, timeout=None, *args, **kwargs) -> Optional[Message]:
|
||||
async def ask(
|
||||
self, chat_id, text, filters=None, timeout=None, *args, **kwargs
|
||||
) -> Optional[Message]:
|
||||
return
|
||||
|
||||
def cancel_listener(self, chat_id):
|
||||
""" Cancel the conversation with the given chat_id. """
|
||||
"""Cancel the conversation with the given chat_id."""
|
||||
return
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user