async def callback_calendar_selector(query, calendar_type='user', move='next', notify_list=None): chat_id = query.message.chat.id if calendar_type == 'user': key = 'user_calendar_selected' elif calendar_type == 'history': key = 'user_calendar_selected_history' selected_date = ctx.get_dispatcher().get(key) if selected_date is not None: if move == 'next': date = next_month(selected_date) elif move == 'prev': date = previous_month(selected_date) year, month = date ctx.get_dispatcher()[key] = date calendar = Calendar(context_data['user_time']) if calendar_type == 'user': markup = calendar.create_selected(year, month) elif calendar_type == 'history': markup = calendar.create_history(year, month, notify_list) return EditMessageReplyMarkup(chat_id=chat_id, message_id=query.message.message_id, reply_markup=markup) else: # Do something to inform of the error pass
async def on_process_message(self, message: types.Message): """ Этот обработчик вызывается, когда диспетчер получает сообщение """ # Получить текущий обработчик handler = context.get_value('handler') # Получить диспетчер из контекста dispatcher = ctx.get_dispatcher() # Если обработчик был настроен, получить ограничение скорости и ключ от обработчика if handler: limit = getattr(handler, 'throttling_rate_limit', self.rate_limit) key = getattr(handler, 'throttling_key', f"{self.prefix}_{handler.__name__}") else: limit = self.rate_limit key = f"{self.prefix}_message" # Использовать Dispatcher.throttle метод try: await dispatcher.throttle(key, rate=limit) except Throttled as t: response = await bot.get_chat_member(message.chat.id, message.from_user.id) if response.status not in admins: # Выполнять действия await self.message_throttled(message, t) # Отменить текущий обработчик raise CancelHandler()
async def on_pre_process_callback_query(call: types.CallbackQuery): """ Этот обработчик вызывается, когда диспетчер получает обновление о нажатии кнопки """ if call.message: if call.message.from_user: # Получить диспетчер из контекста dispatcher = ctx.get_dispatcher() # Использовать Dispatcher.throttle метод try: await dispatcher.throttle('settings_callback', rate=0.5) except Throttled as throttled: response = await bot.get_chat_member( call.message.chat.id, call.from_user.id) if response.status not in admins: # Заблокировать if throttled.exceeded_count <= 2: name = call.from_user.full_name user_id = call.from_user.id await bot.kick_chat_member( call.message.chat.id, user_id, until_date=math.floor(time.time()) + 10 * 60) await bot.send_message( call.message.chat.id, f'[{name}](tg://user?id={user_id}) заблокирован ' 'на 10 минут за бездумное нажатие по кнопкам :).' ) # Отменить текущий обработчик raise CancelHandler()
async def message_throttled(self, message: types.Message, throttled: Throttled): """ Notify user only on first exceed and notify about unlocking only on last exceed :param message: :param throttled: """ from engine import moder chat = message.chat user = message.from_user handler = context.get_value('handler') dispatcher = ctx.get_dispatcher() if handler: key = getattr(handler, 'throttling_key', f"{self.prefix}_{handler.__name__}") else: key = f"{self.prefix}_message" # Calculate how many time is left till the block ends delta = throttled.rate - throttled.delta # Prevent flooding if throttled.exceeded_count <= 2: await moder.restrict_user(chat.id, user.id, FLOOD_MUTE_TIME) await message.reply(FLOOD_LOCK_MESSAGE) # Sleep. await asyncio.sleep(delta) # Check lock status thr = await dispatcher.check_key(key)
async def on_process_message(self, message: types.Message): """ This handler is called when dispatcher receives a message :param message: """ # Get current handler handler = context.get_value('handler') # Get dispatcher from context dispatcher = ctx.get_dispatcher() # If handler was configured, get rate limit and key from handler if handler: limit = getattr(handler, 'throttling_rate_limit', self.rate_limit) key = getattr(handler, 'throttling_key', f"{self.prefix}_{handler.__name__}") else: limit = self.rate_limit key = f"{self.prefix}_message" # Use Dispatcher.throttle method. try: await dispatcher.throttle(key, rate=limit) except Throttled as t: # Execute action await self.message_throttled(message, t) # Cancel current handler raise CancelHandler()
async def message_throttled(self, message: types.Message, throttled: Throttled): """ Notify user only on first exceed and notify about unlocking only on last exceed :param message: :param throttled: """ handler = context.get_value('handler') dispatcher = ctx.get_dispatcher() if handler: key = getattr(handler, 'throttling_key', f"{self.prefix}_{handler.__name__}") else: key = f"{self.prefix}_message" # Calculate how many time left to the end of block. delta = throttled.rate - throttled.delta # Prevent flooding if throttled.exceeded_count <= 2: await message.reply('Too many requests! ') # Sleep. await asyncio.sleep(delta) # Check lock status thr = await dispatcher.check_key(key) # If current message is not last with current key - do not send message if thr.exceeded_count == throttled.exceeded_count: await message.reply('Unlocked.')
async def get_my_calendar_markup(): now = context_data['user_time'] ctx.get_dispatcher()['user_calendar_selected_history'] = (now.year, now.month) calendar = Calendar(now) list_notifications = await get_list_notification_dates( context_data['user_id']) markup = calendar.create_history(now.year, now.month, list_notifications) return markup
async def callback_calendar_select_day_history(query: CallbackQuery): search = re.search('^calendar-day-history-([0-9]{1,2})$', query.data) day = search.group(1) selected_date = ctx.get_dispatcher().get('user_calendar_selected_history') if selected_date is not None: t_selected = datetime.datetime(int(selected_date[0]), int(selected_date[1]), int(day)) ctx.get_dispatcher()['user_calendar_history_date'] = t_selected watch = Watch() notification_list = await get_list_notification_times( context_data['user_id']) markup = watch.create_history_watch(t_selected, notification_list) text = 'Все голосовые заметки на {0}\nВыберите время напоминания:'.format( t_selected.strftime("%Y-%m-%d")) return EditMessageText(chat_id=query.message.chat.id, message_id=query.message.message_id, text=_(text), reply_markup=markup)
async def send_location(message: Message, state_loc=STATE_LOCATION): keyboard_button = KeyboardButton(_('Отправить местоположение'), request_location=True) markup = ReplyKeyboardMarkup([[keyboard_button]], one_time_keyboard=True) state = ctx.get_dispatcher().current_state(chat=message.chat.id, user=message.from_user.id) await state.reset_state() await state.set_state(state_loc) text = _( 'Задайте свой часовой пояс с помощью отправки вашего местоположения.\n' 'Данный функционал доступен только для мобильных устройств') return SendMessage(chat_id=message.chat.id, text=text, reply_markup=markup)
async def set_timezone_by_location_from_voice(message: Message): if hasattr(message.location, 'longitude') & hasattr( message.location, 'latitude'): timezone = utils_timezone.get_by_location(message.location.longitude, message.location.latitude) text = 'Ваш часовой пояс {0}'.format(timezone) else: timezone = utils_timezone.get_default() text = 'Часовой пояс установлен по-умолчанию {0}'.format(timezone) await update_timezone(context_data['user_id'], timezone) now = context_data['user_time'] ctx.get_dispatcher()['user_calendar_selected'] = (now.year, now.month) calendar = Calendar(now) markup = calendar.create_selected(now.year, now.month) state = ctx.get_dispatcher().current_state(chat=message.chat.id, user=message.from_user.id) await state.reset_state() return SendMessage(chat_id=message.chat.id, text=_(text + '\nВыберите дату заметки:'), reply_markup=markup)
async def received_voice(message: Message): now = context_data['user_time'] ctx.get_dispatcher()['user_calendar_selected'] = (now.year, now.month) calendar = Calendar(now) markup = calendar.create_selected(now.year, now.month) if message.voice: voice_id = await create_user_voice_note(context_data['user_id'], message.voice) if context_data['request_timezone']: return await send_location(message, STATE_LOCATION_FROM_VOICE) return SendMessage(chat_id=message.chat.id, text=_('Выберите дату заметки:'), reply_markup=markup)
async def set_timezone_by_location(message: Message): if hasattr(message.location, 'longitude') & hasattr( message.location, 'latitude'): timezone = utils_timezone.get_by_location(message.location.longitude, message.location.latitude) text = 'Установлен часовой пояс: {0}'.format(timezone) else: timezone = utils_timezone.get_default() text = 'Нам не удалось определить часовой пояс по геолокации, по-умолчанию установлен {0}'.format( timezone) await update_timezone(context_data['user_id'], timezone) state = ctx.get_dispatcher().current_state(chat=message.chat.id, user=message.from_user.id) await state.reset_state() return SendMessage(chat_id=message.chat.id, text=_(text), reply_markup=ReplyKeyboardRemove())
async def callback_watch_history_select_time(query: CallbackQuery): search = re.search('^calendar-time-history-([0-9]{1,2})$', query.data) hour = search.group(1) selected_date = ctx.get_dispatcher().get('user_calendar_history_date') if selected_date is not None: notify_date = selected_date.replace(hour=int(hour)) files = await get_list_notes_by_date(context_data['user_id'], notify_date) for file_id in files: bot = ctx.get_bot() await bot.send_voice(chat_id=query.message.chat.id, caption=str(notify_date), voice=file_id) return EditMessageText(chat_id=query.message.chat.id, message_id=query.message.message_id, text=help_text, reply_markup=InlineKeyboardMarkup(), parse_mode=ParseMode.HTML, disable_web_page_preview=True)
async def callback_calendar_select_day(query: CallbackQuery): search = re.search('^calendar-day-([0-9]{1,2})$', query.data) day = search.group(1) selected_date = ctx.get_dispatcher().get('user_calendar_selected') if selected_date is not None: t_selected = datetime.datetime(int(selected_date[0]), int(selected_date[1]), int(day)) note = await get_last_note(context_data['user_id']) if note is not None: notify_id = await create_notification(note.id, t_selected) if notify_id > 0: watch = Watch() markup = watch.create_note_watch() text = '{0}\nВыберите время напоминания:'.format( t_selected.strftime("%Y-%m-%d")) return EditMessageText(chat_id=query.message.chat.id, message_id=query.message.message_id, text=_(text), reply_markup=markup) else: return SendMessage(chat_id=query.message.chat.id, text=_('Ошибка запроса, попробуйте позже'))