def edit_message_text(client: Client, cid: int, mid: int, text: str, markup: InlineKeyboardMarkup = None) -> Union[bool, Message, None]: # Edit the message's text result = None try: if not text.strip(): return None flood_wait = True while flood_wait: flood_wait = False try: result = client.edit_message_text( chat_id=cid, message_id=mid, text=text, parse_mode="html", disable_web_page_preview=True, reply_markup=markup ) except FloodWait as e: flood_wait = True wait_flood(e) except ButtonDataInvalid: logger.warning(f"Edit message {mid} text in {cid} - invalid markup: {markup}") except (ChatAdminRequired, PeerIdInvalid, ChannelInvalid, ChannelPrivate): return False except Exception as e: logger.warning(f"Edit message {mid} in {cid} error: {e}", exc_info=True) return result
def wrapper(*args, **kwargs): result = None while True: try: result = func(*args, **kwargs) except FloodWait as e: wait_flood(e) except Exception as e: logger.warning(f"Retry error: {e}", exc_info=True) break else: break return result
def unban_chat_member(client: Client, cid: int, uid: Union[int, str]) -> Optional[bool]: # Unban a user in a group result = None try: flood_wait = True while flood_wait: flood_wait = False try: result = client.unban_chat_member(chat_id=cid, user_id=uid) except FloodWait as e: flood_wait = True wait_flood(e) except Exception as e: logger.warning(f"Unban chat member {uid} in {cid} error: {e}", exc_info=True) return result
def kick_chat_member(client: Client, cid: int, uid: Union[int, str]) -> Union[bool, Message, None]: # Kick a chat member in a group result = None try: flood_wait = True while flood_wait: flood_wait = False try: result = client.kick_chat_member(chat_id=cid, user_id=uid) except FloodWait as e: flood_wait = True wait_flood(e) except Exception as e: logger.warning(f"Kick chat member {uid} in {cid} error: {e}", exc_info=True) return result
def get_messages(client: Client, cid: int, mids: Iterable[int]) -> Optional[List[Message]]: # Get some messages result = None try: flood_wait = True while flood_wait: flood_wait = False try: result = client.get_messages(chat_id=cid, message_ids=mids) except FloodWait as e: flood_wait = True wait_flood(e) except Exception as e: logger.warning(f"Get messages {mids} in {cid} error: {e}", exc_info=True) return result
def resolve_peer(client: Client, pid: Union[int, str]) -> Union[bool, InputPeerChannel, InputPeerUser, None]: # Get an input peer by id result = None try: flood_wait = True while flood_wait: flood_wait = False try: result = client.resolve_peer(pid) except FloodWait as e: flood_wait = True wait_flood(e) except (PeerIdInvalid, UsernameInvalid, UsernameNotOccupied): return False except Exception as e: logger.warning(f"Resolve peer {pid} error: {e}", exc_info=True) return result
def get_chat(client: Client, cid: Union[int, str]) -> Union[Chat, ChatPreview, None]: # Get a chat result = None try: flood_wait = True while flood_wait: flood_wait = False try: result = client.get_chat(chat_id=cid) except FloodWait as e: flood_wait = True wait_flood(e) except (PeerIdInvalid, ChannelInvalid, ChannelPrivate): return None except Exception as e: logger.warning(f"Get chat {cid} error: {e}", exc_info=True) return result
def leave_chat(client: Client, cid: int, delete: bool = False) -> bool: # Leave a channel try: flood_wait = True while flood_wait: flood_wait = False try: client.leave_chat(chat_id=cid, delete=delete) except FloodWait as e: flood_wait = True wait_flood(e) except (PeerIdInvalid, ChannelInvalid, ChannelPrivate): return False return True except Exception as e: logger.warning(f"Leave chat {cid} error: {e}", exc_info=True) return False
def answer_callback(client: Client, callback_query_id: str, text: str, show_alert: bool = False) -> Optional[bool]: # Answer the callback result = None try: flood_wait = True while flood_wait: flood_wait = False try: result = client.answer_callback_query( callback_query_id=callback_query_id, text=text, show_alert=show_alert ) except FloodWait as e: flood_wait = True wait_flood(e) except QueryIdInvalid: return False except Exception as e: logger.warning(f"Answer query to {callback_query_id} error: {e}", exc_info=True) return result
def get_user_bio(client: Client, uid: int, normal: bool = False, printable: bool = False) -> Optional[str]: # Get user's bio result = None try: user_id = resolve_peer(client, uid) if not user_id: return None flood_wait = True while flood_wait: flood_wait = False try: user: UserFull = client.send(GetFullUser(id=user_id)) if user and user.about: result = t2t(user.about, normal, printable) except FloodWait as e: flood_wait = True wait_flood(e) except Exception as e: logger.warning(f"Get user {uid} bio error: {e}", exc_info=True) return result
def delete_messages(client: Client, cid: int, mids: Iterable[int]) -> Optional[bool]: # Delete some messages result = None try: mids = list(mids) mids_list = [mids[i:i + 100] for i in range(0, len(mids), 100)] for mids in mids_list: try: flood_wait = True while flood_wait: flood_wait = False try: result = client.delete_messages(chat_id=cid, message_ids=mids) except FloodWait as e: flood_wait = True wait_flood(e) except MessageDeleteForbidden: return False except Exception as e: logger.warning(f"Delete message {mids} in {cid} for loop error: {e}", exc_info=True) except Exception as e: logger.warning(f"Delete messages in {cid} error: {e}", exc_info=True) return result
def forward_evidence(client: Client, message: Message, level: str, more: str = None) -> Optional[Union[bool, Message]]: # Forward the message to logging channel as evidence result = None try: if not message or not message.from_user: return result # Basic information uid = message.from_user.id text = (f"{lang('project')}{lang('colon')}{code(glovar.sender)}\n" f"{lang('user_id')}{lang('colon')}{code(uid)}\n" f"{lang('level')}{lang('colon')}{code(level)}\n" f"{lang('rule')}{lang('colon')}{code(lang('rule_admin'))}\n") # Additional information if message.game: text += f"{lang('message_type')}{lang('colon')}{code(lang('gam'))}\n" elif message.service: text += f"{lang('message_type')}{lang('colon')}{code(lang('ser'))}\n" if message.game: text += f"{lang('message_game')}{lang('colon')}{code(message.game.short_name)}\n" if message.from_user.is_self: if message.from_user.is_self is True: if message.entities: for en in message.entities: if not en.user: continue name = get_full_name(en.user) if not name: continue text += f"{lang('user_name')}{lang('colon')}{code(name)}\n" break text += f"{lang('more')}{lang('colon')}{code(lang('from_self'))}\n" # User didn't use report function wisely, should not forward evidence else: text += f"{lang('more')}{lang('colon')}{code(message.from_user.is_self)}" result = send_message(client, glovar.warn_channel_id, text) return result name = get_full_name(message.from_user) if name: text += f"{lang('user_name')}{lang('colon')}{code(name)}\n" if message.service and level == lang("action_ban"): bio = get_user_bio(client, uid) if bio: text += f"{lang('user_bio')}{lang('colon')}{code(bio)}\n" # Extra information if message.contact or message.location or message.venue or message.video_note or message.voice: text += f"{lang('more')}{lang('colon')}{code(lang('privacy'))}\n" elif message.game or message.service: text += f"{lang('more')}{lang('colon')}{code(lang('cannot_forward'))}\n" elif more: text += f"{lang('more')}{lang('colon')}{code(more)}\n" # DO NOT try to forward these types of message if (message.contact or message.location or message.venue or message.video_note or message.voice or message.game or message.service): result = send_message(client, glovar.warn_channel_id, text) return result flood_wait = True while flood_wait: flood_wait = False try: result = message.forward(chat_id=glovar.warn_channel_id, disable_notification=True) except FloodWait as e: flood_wait = True wait_flood(e) except Exception as e: logger.info(f"Forward evidence message error: {e}", exc_info=True) return False result = result.message_id result = send_message(client, glovar.warn_channel_id, text, result) except Exception as e: logger.warning(f"Forward evidence error: {e}", exc_info=True) return result