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
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)
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
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