def start(tguser: TgUser): parts = tguser.message.text.split() if len(parts) == 2: # noinspection PyBroadException try: s = base_utils.real_urlsafe_b64decode( parts[1].encode()).decode() if s.startswith('token:'): p = s.split(':') if len(p) == 2: token_id = p[1] t = Token.objects.filter( id=token_id, created_at__gt=timezone.now() - timedelta(days=1)).first() if t: token = t.token t.delete() tguser.authorize(token) return tguser.render_to_string( 'bot/private/authorized.html', keyboard=keyboards.Start) except Exception as e: pass if not tguser.is_authorized(): PrivateHandler.unauthorized(tguser)
def handle_start(self, msg: types.Message) -> types.Message: """ Handles the `/start [code] [username]` command. :param msg: Message instance :return: API call result """ if msg.text.strip() == "/start": return self.send_message( msg.chat.id, 'Install the <a href="https://github.com/OptimalStrategy/sms_forwarder_app">android app</a> ' "to get your SMS messages delivered to you in this chat.", parse_mode="HTML", ) data = msg.text.split(maxsplit=1) data = data[-1].split("_", maxsplit=1) if len(data) < 2: return self.send_message(msg.chat.id, "Invalid setup command.") code, username = data username = username.lower() # Check if the provided username and the account's username are the same if username != msg.from_user.username.lower(): return self.send_message( msg.chat.id, "You cannot setup the bot for other users.") u = TgUser.by_username(username) if u is None: TgUser.create(msg.chat.id, code, username) else: u.code = code u.save() return self.send_message( msg.chat.id, "Done! You are ready to receive notifications.")
def callback_query_task(function: callable, tgmessage: TgMessage, callback_query: CallbackQuery, tguser: TgUser): logger.debug('callback: %s' % function.__qualname__) tgmessage.fnc, tgmessage.result = exec_task(function, tguser) tgmessage.requests_made = tguser.requests_made tgmessage.save() tguser.answer_callback_query() tguser.save_dirty_fields()
def boards(tguser: TgUser): assert isinstance(tguser.client, TrelloClient) boards = tguser.client.get_boards() timer_board_ids = tguser.timer_set.values_list('board_id', flat=True) tguser.render_to_string('bot/private/choose_board.html', keyboard=keyboards.Boards( tguser, boards, timer_board_ids), edit=True)
def board(tguser: TgUser, board_id=None): if board_id is None: board_id = tguser.callback_query_data_get(1) assert isinstance(tguser.client, TrelloClient) board = tguser.client.get_board(board_id) assert isinstance(board, trolly.Board) lists = board.get_lists() timer_list_ids = tguser.timer_set.values_list('list_id', flat=True) tguser.render_to_string('bot/private/choose_list.html', keyboard=keyboards.Lists(tguser, lists, timer_list_ids), edit=True)
def board_list(tguser: TgUser, list_id=None): if list_id is None: list_id = tguser.callback_query_data_get(1) assert isinstance(tguser.client, TrelloClient) board_list = tguser.client.get_list(list_id) assert isinstance(board_list, trolly.List) cards = board_list.get_cards() timer_card_ids = tguser.timer_set.values_list('card_id', flat=True) tguser.render_to_string('bot/private/choose_card.html', keyboard=keyboards.Cards(tguser, list_id, cards, timer_card_ids), edit=True)
def timer(tguser: TgUser): card_id = tguser.callback_query_data_get(1) assert isinstance(tguser.client, TrelloClient) card = tguser.client.get_card(card_id) assert isinstance(card, trolly.Card) timer = tguser.timer_set.filter(card_id=card_id).first() if not timer: tguser.answer_callback_query('Timer was not started', show_alert=True) raise bot_utils.StateErrorHandler('timer_not_started') tguser.edit_message_reply_markup(keyboard=keyboards.Card(tguser, card_id, timer))
def message_task(function, tgmessage: TgMessage, message: Message, tguser: TgUser): logger.debug('message: %s' % function.__qualname__) tgmessage.fnc, tgmessage.result = exec_task(function, tguser) tgmessage.requests_made = tguser.requests_made if not tguser.id: # was deleted return tgmessage.save() tguser.save_dirty_fields()
def card(tguser: TgUser): card_id = tguser.callback_query_data_get(1) assert isinstance(tguser.client, TrelloClient) card = tguser.client.get_card(card_id) assert isinstance(card, trolly.Card) card_info = card.get_card_information() timer = tguser.timer_set.filter(card_id=card_id).first() message = tguser.render_to_string('bot/private/show_card.html', context=dict(card=card_info), keyboard=keyboards.Card(tguser, card_id, timer), edit=True) if timer: assert isinstance(message, Message) timer.message_id = message.message_id timer.save()
def back(tguser: TgUser): obj_type = tguser.callback_query_data_get(1) obj_id = tguser.callback_query_data_get(2) assert isinstance(tguser.client, TrelloClient) if obj_type == 'card': card = tguser.client.get_card(obj_id) assert isinstance(card, trolly.Card) card_info = card.get_card_information() return PrivateHandler.board_list(tguser, card_info['idList']) if obj_type == 'list': board_list = tguser.client.get_list(obj_id) assert isinstance(board_list, trolly.List) board = board_list.get_board() return PrivateHandler.board(tguser, board.id) PrivateHandler.boards(tguser)
def forward_sms(request: HttpRequest) -> HttpResponse: """ Forwards an SMS message to a user. @endpoint /forward @param ?code=<code> @param &username=<username> @params [&{address, body, date}] """ # Check for required params if "code" not in request.GET: return HttpResponse(b"The `code` param must be provided.", status=400) if "username" not in request.GET: return HttpResponse(b"The `username` param must be provided.", status=400) code = request.GET.get("code") username = request.GET.get("username") address, body, date = [ request.GET.get(f, "<>") for f in ("address", "body", "date") ] user = TgUser.by_username(username) if user is None: return HttpResponse(b"Such user does not exist.", status=404) if user.code != code: return HttpResponse(b"Bad code.", status=401) bot_instance.send_message( user.telegram_id, f"New SMS message from '{address}':\n{body}\n\nDate: {date}." ) return HttpResponse(status=200)
def exec_task(function, tguser: TgUser): check_result = tguser.checks(function) result = '' fnc = function.__qualname__ if check_result is True: try: res = function(tguser) if res is False: result = 'fail' else: result = 'ok' except bot_utils.BaseErrorHandler as e: name = base_utils.un_camel(e.__class__.__name__).replace( '_handler', '') result = '%s:%s' % (name, str(e)) else: result = 'checks:' + check_result tguser.update_last_active() return fnc, result
def timer_plus(tguser: TgUser): card_id = tguser.callback_query_data_get(1) minutes = tguser.callback_query_data_get(2, as_int=True) assert isinstance(tguser.client, TrelloClient) card = tguser.client.get_card(card_id) assert isinstance(card, trolly.Card) timer = tguser.timer_set.filter(card_id=card_id).first() if not timer: tguser.answer_callback_query('Timer was not started', show_alert=True) raise bot_utils.StateErrorHandler('timer_not_started') assert isinstance(timer, Timer) timer.created_at = timer.created_at - timedelta(minutes=minutes) timer.save() tguser.answer_callback_query('Timer was increased on %s minutes' % minutes) tguser.edit_message_reply_markup(keyboard=keyboards.Card(tguser, card_id, timer))
def timer_add(tguser: TgUser): seconds = int(tguser.callback_query_data_get(1)) card_id = tguser.callback_query_data_get(2) timer = tguser.timer_set.filter(card_id=card_id).first() if not timer: tguser.answer_callback_query('Timer was not started', show_alert=True) raise bot_utils.StateErrorHandler('timer_not_started') to_add = timedelta(seconds=seconds) timer.created_at = timer.created_at - to_add timer.save() tguser.answer_callback_query('Added %s' % to_add) tguser.edit_message_reply_markup(keyboard=keyboards.Card(tguser, card_id, timer))
def check_user(request: HttpRequest) -> HttpResponse: """ Returns 200 if the user exists. @endpoint /check_user @param ?username=<username> @param [& code] """ if "username" not in request.GET: return HttpResponse(b"The `username` param must be provided.", status=400) user = TgUser.by_username(request.GET.get("username")) if user is None: return HttpResponse(b"Such user does not exist.", status=404) if request.GET.get("code", -1) != user.code: return HttpResponse(b"Bad code.", status=400) return HttpResponse(b"OK", status=200)
def _notify_command_handlers(self, handlers, items): for item in items: with base_utils.lock('tguser_%d' % item.from_user.id): with transaction.atomic(): tguser = TgUser.load(item.from_user, item) assert isinstance(tguser, TgUser) if settings.UNDER_CONSTRUCTION and not tguser.is_admin(): tguser.send_message(_('The bot is under construction...'), reply=True, reply_markup=ReplyKeyboardRemove()) continue tries = 0 while True: tries += 1 try: next_raised = False for handler in handlers: if self._test_message_handler( handler, item, tguser): try: if isinstance(item, CallbackQuery): self._before_exec_callback_query_task( handler, item, tguser) elif isinstance(item, Message): self._before_exec_message_task( handler, item, tguser) next_raised = False except bot_utils.NextHandler: next_raised = True continue break else: if settings.DEBUG: logger.debug('Unhandled update: %s', item) if next_raised: logger.warning( 'NextHandler raised but was not proceed! TgUser: %s, message: %s', tguser, base_utils.to_json(item, indent=None)) except bot_utils.RestartHandler: if tries >= 10: raise continue else: break
def timer_stop(tguser: TgUser): card_id = tguser.callback_query_data_get(1) assert isinstance(tguser.client, TrelloClient) card = tguser.client.get_card(card_id) assert isinstance(card, trolly.Card) timer = tguser.timer_set.filter(card_id=card_id).first() if not timer: tguser.answer_callback_query('Timer was not started', show_alert=True) raise bot_utils.StateErrorHandler('timer_not_started') assert isinstance(timer, Timer) dur = timezone.now() - timer.created_at d = '%.2f' % (dur.seconds / 3600) card.add_comments('plus! %s/%s' % (d, d)) timer.delete() logged = mytime(dur, True) tguser.answer_callback_query('Logged %s' % logged) tguser.edit_message_reply_markup(keyboard=keyboards.Card(tguser, card_id, None))
def timer_start(tguser: TgUser): card_id = tguser.callback_query_data_get(1) assert isinstance(tguser.client, TrelloClient) card = tguser.client.get_card(card_id) assert isinstance(card, trolly.Card) timer = tguser.timer_set.filter(card_id=card_id).first() if timer: tguser.answer_callback_query('Timer was already started', show_alert=True) raise bot_utils.StateErrorHandler('timer_already_started') if tguser.timer_set.exists(): tguser.answer_callback_query('You cannot start more than one timer simultaneously', show_alert=True) raise bot_utils.StateErrorHandler('multiple_timers') card_info = card.get_card_information() timer = tguser.timer_set.create( board_id=card_info['idBoard'], list_id=card_info['idList'], card_id=card_id, message_id=tguser.callback_query.message.message_id, ) tguser.edit_message_reply_markup(keyboard=keyboards.Card(tguser, card_id, timer))
def me(tguser: TgUser): tguser.send_message(serializers.serialize('json', [tguser], indent=True, ensure_ascii=False))
def error_fixed(tguser: TgUser): tguser.edit_message_text('Marked as fixed with %s' % tguser)
def unauthorized(cls, tguser: TgUser): assert isinstance(tguser.client, TrelloClient) url = tguser.client.get_authorisation_url() tguser.render_to_string('bot/private/errors/not_authorized.html', context=dict(url=url), edit=True)
def settings(tguser: TgUser): tguser.send_message('Настроек пока нет', keyboard=keyboards.Start)
def help(tguser: TgUser): tguser.render_to_string('bot/private/help.html', keyboard=keyboards.Start)
def unknown_content_type(tguser: TgUser): tguser.render_to_string('bot/private/errors/unknown_content_type.html', keyboard=keyboards.Start) if tguser.after_unknown_text: tguser.after_unknown_text(tguser)
def cancel(tguser: TgUser): tguser.reset() tguser.render_to_string('bot/private/canceled.html', keyboard=keyboards.Start)
def unknown_text(tguser: TgUser): tguser.render_to_string('bot/private/errors/unknown_text.html', keyboard=keyboards.Start) if tguser.after_unknown_text: tguser.after_unknown_text(tguser) OtherHandler.send_to_feedback_tgchat(tguser, feedback_tgchat())
def deleteme(tguser: TgUser): tguser.delete() reply_markup = ReplyKeyboardRemove() tguser.send_message('Deleted', reply_markup=reply_markup)
def edit_message(tguser: TgUser): tguser.render_to_string('bot/private/errors/cannot_edit_message.html')