Beispiel #1
0
    async def _run_state(self, responder, state, trigger, request) \
            -> BaseState:
        """
        Execute the state, or if execution fails handle it.
        """

        # noinspection PyBroadException
        try:
            if trigger:
                await state.handle()
            else:
                await state.confused()

            for i in range(0, settings.MAX_INTERNAL_JUMPS + 1):
                if i == settings.MAX_INTERNAL_JUMPS:
                    raise MaxInternalJump()

                trigger, state_class = \
                    await self._find_trigger(request, state.name(), True)

                if not trigger:
                    break

                logger.debug('Jumping to state: %s', state_class.name())
                state = state_class(request, responder)
                await state.handle()
        except Exception:
            logger.exception('Error while handling state "%s"', state.name())
            responder.clear()
            reporter.report(request, state.name())
            await state.error()

        return state
Beispiel #2
0
    async def _send_to_messenger_profile(self, page, content):
        """
        The messenger profile API handles all meta-information about the bot,
        like the menu. This allows to submit data to this API endpoint.

        :param page: page dict from the configuration
        :param content: content to be sent to Facebook (as dict)
        """

        log_name = ', '.join(repr(x) for x in content.keys())
        page_id = page['page_id']

        current = await self._get_messenger_profile(page, content.keys())

        if dict_is_subset(content, current):
            logger.info('Page %s: %s is already up to date', page_id, log_name)
            return

        params = {
            'access_token': page['page_token'],
        }

        headers = {
            'content-type': 'application/json',
        }

        post = self.session.post(PROFILE_ENDPOINT,
                                 params=params,
                                 headers=headers,
                                 data=ujson.dumps(content))

        # noinspection PyBroadException
        try:
            async with post as r:
                await self._handle_fb_response(r)
        except Exception:
            logger.exception('Page %s: %s could not be set', page_id, log_name)
            reporter.report()
        else:
            logger.info('Page %s: %s was updated', page_id, log_name)
Beispiel #3
0
    async def _handle_message(self,
                              message: BaseMessage,
                              responder: Responder) -> Optional[Dict]:
        """
        Handles a message: find a state and run it.

        :return: The register that was saved
        """

        reg_manager = self.register\
            .work_on_register(message.get_conversation().id)

        async with reg_manager as reg:
            request = Request(message, reg)
            await request.transform()

            try:
                state, trigger = \
                    await self._build_state(request, message, responder)
            except Exception:
                reporter.report(request, None)
                logger.exception('Error while finding a transition from %s',
                                 reg.get(Register.STATE))
                return

            if state is None:
                return

            state = await self._run_state(responder, state, trigger, request)

            # noinspection PyBroadException
            try:
                await responder.flush(request)
            except MissingTranslationError as e:
                responder.clear()
                responder.send([RawText(str(e))])
                await responder.flush(request)

                reporter.report(request, state.name())
                logger.exception('Missing translation in state %s',
                                 state.name())
            except Exception:
                reporter.report(request, state.name())
                logger.exception('Could not flush content after %s',
                                 state.name())
            else:
                reg.replacement = \
                    await self._build_state_register(state, request, responder)
                return reg.replacement
Beispiel #4
0
    async def _handle_message(self, message: BaseMessage,
                              responder: Responder) -> Optional[Dict]:
        """
        Handles a message: find a state and run it.

        :return: The register that was saved
        """
        async def noop(request: Request, responder: Responder):
            pass

        mm = MiddlewareManager.instance()
        reg_manager = self.register\
            .work_on_register(message.get_conversation().id)

        async with reg_manager as reg:
            request = Request(message, reg)
            await request.transform()

            if not request.stack.layers:
                return

            logger.debug('Incoming message: %s', request.stack)
            await mm.get('pre_handle', noop)(request, responder)

            # noinspection PyBroadException
            try:
                state, trigger, dnr = \
                    await self._build_state(request, message, responder)
            except Exception:
                logger.exception('Error while finding a transition from %s',
                                 reg.get(Register.STATE))
                reporter.report(request, None)
                return

            if state is None:
                logger.debug(
                    'No next state found but "%s" is not confusing, stopping',
                    request.message,
                )
                return

            state = await self._run_state(responder, state, trigger, request)

            # noinspection PyBroadException
            try:
                await responder.flush(request)
            except MissingTranslationError as e:
                responder.clear()
                responder.send([RawText(str(e))])
                await responder.flush(request)

                reporter.report(request, state.name())
                logger.exception('Missing translation in state %s',
                                 state.name())
            except Exception:
                reporter.report(request, state.name())
                logger.exception('Could not flush content after %s',
                                 state.name())
            else:
                if not dnr:
                    reg.replacement = await self._build_state_register(
                        state,
                        request,
                        responder,
                    )
                return reg.replacement