async def respond(self, event: NewMessage.Event, msg: Union[str, KanTeXDocument], reply: bool = True, delete: Optional[str] = None, link_preview: bool = False) -> Message: """Respond to the message an event caused or to the message that was replied to Args: event: The event of the message msg: The message text reply: If it should reply to the message that was replied to delete: Seconds until the sent message should be deleted Returns: None """ msg = str(msg) if reply: if isinstance(event, ChatAction.Event): reply_to = event.action_message.id else: reply_to = (event.reply_to_msg_id or event.message.id) sent_msg: Message = await event.respond(msg, reply_to=reply_to, link_preview=link_preview) else: sent_msg: Message = await event.respond(msg, link_preview=link_preview) if delete is not None: delete_in = parsers.time(delete) # While asyncio.sleep would work it would stop the function from returning which is annoying await self.send_message(sent_msg.chat, f'{self.config.prefix}delete [Scheduled deletion]', schedule=datetime.timedelta(seconds=delete_in), reply_to=sent_msg.id, link_preview=link_preview) return sent_msg
async def time(args: List[str]) -> MDTeXDocument: """Parse specified duration expressions into timedeltas Arguments: `exprs`: Time expressions Examples: {cmd} 1d {cmd} 1h30m 20s1m {cmd} 2w3d3h5s """ m = Section('Parsed Durations') for arg in args: seconds = parsers.time(arg) m.append( SubSection( arg, KeyValueItem('seconds', seconds), KeyValueItem('formatted', str(timedelta(seconds=seconds))))) return MDTeXDocument(m)
async def lock(client: Client, db: Database, chat: Chat, event: Command, msg: Message, args) -> KanTeXDocument: """Set a chat to read only. Arguments: `duration`: How long the chat should be locked `-self`: Use to make other Kantek instances ignore your command Examples: {cmd} 2h {cmd} 1d {cmd} """ participant = (await client(GetParticipantRequest(chat, msg.from_id))).participant permitted = False if isinstance(participant, ChannelParticipantCreator): permitted = True elif isinstance(participant, ChannelParticipantAdmin): rights = participant.admin_rights permitted = rights.ban_users if not permitted: return KanTeXDocument('Insufficient permission.') duration = None if args: try: duration = parsers.time(args[0]) except MissingExpression as err: return KanTeXDocument(Italic(err)) if duration and duration < 10: return KanTeXDocument('Duration too short.') permissions = chat.default_banned_rights.to_dict() del permissions['_'] del permissions['until_date'] del permissions['view_messages'] await db.chats.lock(event.chat_id, {k: v for k, v in permissions.items() if not v}) try: await client( EditChatDefaultBannedRightsRequest(chat, banned_rights=ChatBannedRights( until_date=None, view_messages=None, send_messages=True, send_media=True, send_stickers=True, send_gifs=True, send_games=True, send_inline=True, send_polls=True, change_info=True, invite_users=True, pin_messages=True))) if duration: config = Config() await client.send_message(chat, f'{config.prefix}unlock', schedule=msg.date + timedelta(seconds=duration)) return KanTeXDocument('Chat locked.') except ChatNotModifiedError: return KanTeXDocument('Chat already locked.')
async def schedule(client: Client, chat: Channel, msg: Message, kwargs: Dict, event: Command) -> KanTeXDocument: """Schedule commands from a file or a message One command per line. Must be in reply to either a message or a file. Arguments: `-overwrite`: Overwrite all currently scheduled commands `-dynamic`: Determine the offset between messages dynamically depending on the messages word count `offset`: Offset as duration expression, see `{prefix}help parsers time` Examples: {cmd} -overwrite {cmd} -overwrite -dynamic {cmd} -overwrite offset: 30m """ offset = kwargs.get('offset', '1h') offset = parsers.time(offset) dynamic = kwargs.get('dynamic', False) if kwargs.get('overwrite'): scheduled = await client(GetScheduledHistoryRequest(chat, 0)) scheduled_ids = [smsg.id for smsg in scheduled.messages] await client(DeleteScheduledMessagesRequest(chat, scheduled_ids)) if msg.is_reply: reply_msg: Message = await msg.get_reply_message() if isinstance(reply_msg.media, MessageMediaDocument): commands = (await reply_msg.download_media(bytes)).decode().split('\n') else: commands = reply_msg.text.split('\n') current = datetime.now() next_time = current.astimezone(timezone.utc) next_time += timedelta(seconds=15) from_time = next_time for cmd in commands: if cmd: if dynamic: offset = (len(cmd.split())**0.7) * 60 try: await client.send_message(chat, cmd, schedule=next_time) except FloodWaitError as err: await msg.edit( f'FloodWait. Sleeping for {err.seconds} seconds.') await asyncio.sleep(err.seconds) next_time += timedelta(seconds=offset) await asyncio.sleep(0.5) await event.delete() return KanTeXDocument( Section( 'Scheduled Messages', KeyValueItem( Bold('From'), from_time.astimezone( current.tzinfo).strftime('%Y-%m-%d %H:%M:%S')), KeyValueItem( Bold('To'), next_time.astimezone( current.tzinfo).strftime('%Y-%m-%d %H:%M:%S')), KeyValueItem(Bold('Count'), Code(len(commands)))))