fix: a bug

This commit is contained in:
xtaodada 2023-09-11 21:05:50 +08:00
parent 4ff489cf95
commit 060aa7b8fa
Signed by: xtaodada
GPG Key ID: 4CBB3F4FA8C85659
14 changed files with 170 additions and 109 deletions

View File

@ -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 {
ChatMemberStatus.ADMINISTRATOR,
ChatMemberStatus.OWNER,
ChatMemberStatus.MEMBER,
ChatMemberStatus.RESTRICTED,
}:
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")

View File

@ -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")

View File

@ -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(
"邀请入群",
url=f"https://t.me/{me.username}?startgroup=start&admin=can_invite_users")]
]))
[
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",
)
],
]
),
)

View File

@ -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

View File

@ -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)]

View File

@ -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,25 +91,25 @@ 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 listener["filters"](client, update)
if callable(listener["filters"])
else 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
@patch(pyrogram.types.user_and_chats.chat.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

View File

@ -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)

View File

@ -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")

View File

@ -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

View File

@ -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_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"})
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"},
)
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>

View File

@ -9,4 +9,5 @@ async def main():
await idle()
await bot.stop()
bot.run(main())

View File

@ -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)

View File

@ -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()

View File

@ -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