예제 #1
0
 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)
예제 #2
0
    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.")
예제 #3
0
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()
예제 #4
0
 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)
예제 #5
0
 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)
예제 #6
0
 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)
예제 #7
0
 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))
예제 #8
0
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()
예제 #9
0
 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()
예제 #10
0
 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)
예제 #11
0
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)
예제 #12
0
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
예제 #13
0
 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))
예제 #14
0
    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))
예제 #15
0
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)
예제 #16
0
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
예제 #17
0
 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))
예제 #18
0
 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))
예제 #19
0
 def me(tguser: TgUser):
     tguser.send_message(serializers.serialize('json', [tguser], indent=True, ensure_ascii=False))
예제 #20
0
 def error_fixed(tguser: TgUser):
     tguser.edit_message_text('Marked as fixed with %s' % tguser)
예제 #21
0
 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)
예제 #22
0
 def settings(tguser: TgUser):
     tguser.send_message('Настроек пока нет', keyboard=keyboards.Start)
예제 #23
0
 def help(tguser: TgUser):
     tguser.render_to_string('bot/private/help.html', keyboard=keyboards.Start)
예제 #24
0
 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)
예제 #25
0
 def cancel(tguser: TgUser):
     tguser.reset()
     tguser.render_to_string('bot/private/canceled.html',
                             keyboard=keyboards.Start)
예제 #26
0
 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())
예제 #27
0
 def deleteme(tguser: TgUser):
     tguser.delete()
     reply_markup = ReplyKeyboardRemove()
     tguser.send_message('Deleted', reply_markup=reply_markup)
예제 #28
0
 def edit_message(tguser: TgUser):
     tguser.render_to_string('bot/private/errors/cannot_edit_message.html')