예제 #1
0
class SeatState(BaseState):
    choices = tuple(range(1, 5))

    _intro_message = BotMessage(_('How many seats?'), buttons=[
        [{
            'text': str(x),
            'data': str(x),
        } for x in choices],
        [BACK]
    ])

    async def get_back_state(self):
        if self.data.get('seat'):
            return 'purchase'

        return 'show'

    async def process(self):
        try:
            seat_number = int(self.value)
        except ValueError:
            self.message_was_not_recognized = True
            return

        if seat_number not in self.choices:
            self.message_was_not_recognized = True
            return

        self.set_state('purchase')
예제 #2
0
class PhoneState(BaseState):
    _intro_message = BotMessage(
        text=_('Tap the button below to share your phone number or enter it.'),
        buttons=[
            [{
                'text': _('Share phone number'),
                'type': 'phone',
            }],
            [_('⬅ Back')]
        ],
        is_tg_text_buttons=True
    )

    async def get_back_state(self):
        return 'purchase' if self.user.phone else 'show'

    async def process(self):
        if self.text and self.text.startswith('⬅'):
            self.set_state(await self.get_back_state())
            return

        phone = (self.contact and self.contact.phone) or validate_phone(self.text)

        if phone is None:
            self.message_was_not_recognized = True
            return

        self.user.phone = phone
        self.set_state('purchase')
예제 #3
0
    def get_intro_message(self):
        trip_service = TripService.get_service(self.data['show'])

        stations = trip_service.get_stations()

        if stations.count() == 0:
            raise ValueError(f'There are no stations available in db for '
                             f'provider {trip_service.provider_name()}'
                             f'and direction {trip_service.direction_name()}')

        buttons = [[{'text': x.name, 'data': str(x.id)}] for x in stations]

        viber_limit_with_back = VIBER_ROWS_LIMIT - 1
        viber_limit_with_back_and_navigate = viber_limit_with_back - 1

        if len(buttons) > viber_limit_with_back:
            if self.data.get('station__last'):
                buttons = buttons[viber_limit_with_back_and_navigate:]
                buttons.insert(0, [{
                    'text': _('...previous'),
                    'data': 'first',
                }])

            else:
                buttons = buttons[:viber_limit_with_back_and_navigate]
                buttons.append([{
                    'text': _('more...'),
                    'data': 'last',
                }])

        buttons.append([BACK])
        return BotMessage(_('Choose start station:'), buttons=buttons)
예제 #4
0
def to_telegram_message(message: BotMessage, chat_id):
    formatted = {
        'text': message.text,
        'method': TelegramMethod.SEND_MESSAGE,
        'chat_id': chat_id,
    }

    if message.parse_mode:
        formatted['parse_mode'] = message.parse_mode

    buttons = message.get_tg_buttons()

    if buttons:

        if message.is_tg_text_buttons:
            formatted['reply_markup'] = {
                'keyboard': TextButtonFormatter.format_list(buttons),
                'resize_keyboard': True,
                'one_time_keyboard': True,
            }

        else:
            formatted['reply_markup'] = {
                'inline_keyboard': InlineButtonFormatter.format_list(buttons),
            }

    return formatted
예제 #5
0
    def get_intro_message(self):
        db = get_db()
        trip = db.query(Trip).get(self.data['show'])

        return BotMessage(
            text=self.get_text(trip),
            buttons=self.get_buttons()
        )
예제 #6
0
class NotesState(BaseState):
    back = 'purchase'

    _intro_message = BotMessage(_('Add some notes:'),
                                buttons=[[BACK]],
                                is_text_input=True)

    async def process(self):
        notes = (self.text or '').strip()
        self.data[self.get_name()] = notes
        self.set_state('purchase')
예제 #7
0
    def get_intro_message(self):
        purchases = tuple(UserService(self.user).future_purchases())
        if not purchases:
            return BotMessage(_('You have no pending trips'), buttons=[[BACK]])

        buttons = []
        for purchase in purchases:
            buttons.append([{
                'text': self.build_purchase_label(purchase),
                'data': 'show_{}'.format(purchase.id),
            }, {
                'text': b'\xE2\x9D\x8C'.decode('utf-8'),
                'data': 'cancel_{}'.format(purchase.id),
            }])

        buttons.append([BACK])

        text = _('Your purchases') if len(purchases) > 1 else _(
            'Your purchase')

        return BotMessage(text, buttons)
예제 #8
0
def to_viber_message(bot_message: BotMessage, receiver) -> dict:
    viber_message = build_basic_message(bot_message)

    buttons = bot_message.get_viber_buttons()

    if buttons:
        add_keyboard_into_message(viber_message,
                                  buttons,
                                  hide_input=not bot_message.is_text_input)

    viber_message['receiver'] = receiver.id
    return viber_message
예제 #9
0
    def get_intro_message(self):
        if self.is_wrong_sms():
            text = _('Wrong SMS code.')
            buttons = [[BACK, {
                'text': _('Send again'),
                'data': 'resend',
            }]]

        else:
            text = _('SMS was sent to +%s. Enter it.') % self.user.phone
            buttons = [[BACK]]

        return BotMessage(
            text=text,
            buttons=buttons,
            is_text_input=True,
        )
예제 #10
0
    def get_intro_message(self):
        trip_id_list = self.data['trip_id_list']
        show_shorten = (len(trip_id_list) >
                        4) and not self.data.get(FULL_TRIPS_SWITCH)

        if show_shorten:
            trip_id_list = trip_id_list[:3]

        trips = TripService.id_list(trip_id_list).order_by(Trip.start_datetime)
        buttons = [trip_to_line(trip) for trip in trips]

        if show_shorten:
            buttons.append([{
                'text': _('More'),
                'data': 'full',
            }])

        buttons.append([BACK])
        return BotMessage(text=_('Choose trip:'), buttons=buttons)
예제 #11
0
class FirstNameState(BaseState):
    async def get_back_state(self):
        if self.user.first_name:
            return 'purchase'

        return 'show'

    _intro_message = BotMessage(text=_("What's your name?"),
                                buttons=[[BACK]],
                                is_text_input=True)

    async def process(self):
        if self.text:
            self.text = self.text.strip()

        if not self.text:
            self.message_was_not_recognized = True
            return

        self.user.first_name = self.text
        self.set_state('purchase')
예제 #12
0
 def test_get_viber_buttons__none(self):
     tested = BotMessage('Hello')
     assert tested.get_viber_buttons() is None
예제 #13
0
    def test_get_viber_buttons(self):
        tested = BotMessage(buttons=[
            [
                {
                    'text': '1.1',
                    'data': '1.1',
                },
                {
                    'text': '1.2',
                    'data': '1.2',
                },
                {
                    'text': '1.3',
                    'data': '1.3',
                },
            ],
            [
                {
                    'text': '2.1',
                    'data': '2.1',
                },
                {
                    'text': '2.2',
                    'data': '2.2',
                },
            ],
            [
                {
                    'text': '3.1',
                    'data': '3.1',
                },
            ],
        ])

        assert tested.get_viber_buttons() == [
            {
                'text': '1.1',
                'data': '1.1',
                'viber': {
                    'Columns': 2,
                },
            },
            {
                'text': '1.2',
                'data': '1.2',
                'viber': {
                    'Columns': 2,
                },
            },
            {
                'text': '1.3',
                'data': '1.3',
                'viber': {
                    'Columns': 2,
                },
            },
            {
                'text': '2.1',
                'data': '2.1',
                'viber': {
                    'Columns': 3,
                },
            },
            {
                'text': '2.2',
                'data': '2.2',
                'viber': {
                    'Columns': 3,
                },
            },
            {
                'text': '3.1',
                'data': '3.1',
                'viber': {
                    'Columns': 6,
                },
            },
        ]
 def get_intro_message(self):
     return BotMessage(
         text=_('SMS was sent to +%s. Enter it.') % self.user.phone,
         buttons=[[BACK]],
         is_text_input=True,
     )
예제 #15
0
class WhereState(BaseState):
    """
    Store where we are going and ask WHEN?
    """
    with_trips_intro_message = BotMessage(text=_('Where are we going?'),
                                          buttons=[[{
                                              'text':
                                              _('To Mogilev'),
                                              'data':
                                              Trip.MINSK_MOG_DIRECTION,
                                          }, {
                                              'text':
                                              _('To Minsk'),
                                              'data':
                                              Trip.MOG_MINSK_DIRECTION,
                                          }],
                                                   [{
                                                       'text': _('My trips'),
                                                       'data': 'purchase_list'
                                                   }],
                                                   [{
                                                       'text': _('Feedback'),
                                                       'data': 'feedback',
                                                   }]])

    no_trips_intro_message = BotMessage(text=_('Where are we going?'),
                                        buttons=[[{
                                            'text':
                                            _('To Mogilev'),
                                            'data':
                                            Trip.MINSK_MOG_DIRECTION,
                                        }, {
                                            'text':
                                            _('To Minsk'),
                                            'data':
                                            Trip.MOG_MINSK_DIRECTION,
                                        }],
                                                 [{
                                                     'text': _('Feedback'),
                                                     'data': 'feedback',
                                                 }]])

    def get_intro_message(self):
        if not UserService(self.user).future_purchases().count():
            return self.no_trips_intro_message

        return self.with_trips_intro_message

    async def process(self):
        if self.value in (Trip.MOG_MINSK_DIRECTION, Trip.MINSK_MOG_DIRECTION):
            self.set_state('date')
            return

        if self.value == 'purchase_list':
            self.set_state('purchaselist')
            return

        if self.value == 'feedback':
            self.set_state('feedback')
            return

        self.message_was_not_recognized = True
예제 #16
0
class FeedbackState(BaseState):
    back = 'where'

    greeting_intro_message = BotMessage(
        _('Send me some feedback. '
            'What would you improve, '
            'what went wrong while using the bot?\n'
            'It will help me become better.'),
        buttons=[[BACK]],
        is_text_input=True
    )

    continue_intro_message = BotMessage(
        _('Add anything or press "Back" to return to booking trips.'),
        buttons=[[BACK]],
        is_text_input=True
    )

    def get_intro_message(self):
        if self.data.pop('feedback__continue', False):
            return self.continue_intro_message

        return self.greeting_intro_message

    async def process(self):
        bot = self.get_bot()

        logger.warning(
            'Got %s feedback!\n---\n%s\n---\n'
            'User: first_name - %s; phone - %s\n'
            'Context: %s',
            bot, self.text, self.user.first_name, self.user.phone, self.data,
            extra={
                'tags': {
                    'event': 'feedback',
                    'bot': bot,
                },
            },
        )

        if not self.text:
            if bot == TELEGRAM_BOT:
                contact = TG_CONTACT

            else:
                contact = VIBER_CONTACT

            self.add_message(_(
                "Excuse me, I can't recognize your message :( "
                "Please, contact me directly at %s to tell what you wanted."
            ) % contact)

        else:
            ConversationService.add_user_message(
                self.user,
                self.text,
                self.data,
                bot
            )

        self.data['feedback__continue'] = True
예제 #17
0
 def get_intro_message(self):
     return BotMessage(self.TEXT, [self.buttons, [BACK]])