def Resolve(obj, variables): """Resolve text into variable value.""" if not IsVariable(obj) or variables is None: return obj m = VARIABLE_RE.match(str(obj)) if not m: return obj names = m.group(1) if ',' in names: options = names.split(',') else: options = [names] for option in options: if '#' in option: try: parts = option.split('#') if parts[0] in variables: return variables[parts[0]][int(parts[1])] except Exception as e: logger.exception(e) continue else: if option in variables: return variables[option] return obj
def line_receive(provider_ident): """LINE Bot API receive.""" try: if config.DEPLOY: line_webhook_task.apply_async((provider_ident, )) else: line_webhook_task(provider_ident) except Exception as e: logger.exception(e) return 'ok'
def __init__(self): self._api = None try: pb2_module, addr = GetgRPCService('youbike') channel = grpc.insecure_channel('%s:%d' % addr) self._stub = pb2_module.YoubikeInfoStub(channel) self._pb2_module = pb2_module except Exception as e: logger.exception(e) self._stub = None
def facebook_receive(): """Facebook Bot API receive.""" try: if config.DEPLOY: facebook_webhook_task.apply_async() else: facebook_webhook_task() except Exception as e: logger.exception(e) return 'ok'
def average_waiting_time(self, sno, direction): try: response = self._stub.GetAverageWaitingTime( self._pb2_module.GetAverageWaitingTimeRequest( sno=sno, direction=direction.value), GRPC_TIMEOUT) return response.minutes except Exception as e: logger.exception(e) # Just return 10 minutes when we have no data. return 10
def find_knn(self, k, coordinate, threshold=0): try: response = self._stub.FindKnn( self._pb2_module.FindKnnRequest( k=k, lat=coordinate[0], long=coordinate[1], threshold=threshold), GRPC_TIMEOUT) return cPickle.loads(response.object) except Exception as e: logger.exception(e) return self._youbike_api().find_knn(k, coordinate, threshold)
def create_broadcast(): """Create a new broadcast.""" try: broadcast_json = request.json broadcast_json['account_id'] = g.account.id broadcast = parse_broadcast(broadcast_json) except Exception as e: logger.exception(e) raise AppError(HTTPStatus.STATUS_CLIENT_ERROR, CustomError.ERR_WRONG_PARAM, 'Broadcast create request failed') DatabaseManager.commit() return jsonify(broadcast.to_json())
def create_platform(): """Create a new platform.""" try: platform_json = request.json platform_json['account_id'] = g.account.id platform = parse_platform(platform_json) except Exception as e: logger.exception(e) raise AppError(HTTPStatus.STATUS_CLIENT_ERROR, CustomError.ERR_WRONG_PARAM, 'Platform definition parsing failed') DatabaseManager.commit() return jsonify(platform.to_json(['config']))
def deploy_bot(bot_id): bot = get_account_bot_by_id(bot_id) try: parse_bot(bot.staging, bot.id) except Exception as e: logger.exception(e) raise AppError(HTTPStatus.STATUS_CLIENT_ERROR, CustomError.ERR_WRONG_PARAM, 'Bot definition parsing failed') bot_def = BotDef.add_version(bot.id, bot.staging) bot.staging = None # Clear staging area DatabaseManager.commit() return jsonify(version=bot_def.version)
def refresh_data(self): """Refresh Youbike data. First try the pickle method. If it fails, fallback to the youbike PHP method. If it also fails, fallback to the data.taipi API. """ # exception if no pickle file or len(stations_history) < 1 try: self._fetch_data_youbike_php() except Exception as e: logger.exception(e) self._fetch_data_taipei_data() self._parse_data()
def RunInputTransformation(self): """Perform input transformation if there is one.""" try: if (self.text and g.user and g.user.session and g.user.session.input_transformation): ret = InputTransformation.transform( self.text, g.user.session.input_transformation) return ret if ret else self except Exception as e: # We shouldn't block user if input transformation fail (possibly # due to invalid regular expression). Log the failure for # analysis. logger.exception(e) return self
def update_bot(bot_id): """Modify a bot staging area.""" bot = get_account_bot_by_id(bot_id) try: validate_bot_schema(request.json) except Exception as e: logger.exception(e) raise AppError(HTTPStatus.STATUS_CLIENT_ERROR, CustomError.ERR_WRONG_PARAM, 'Bot definition parsing failed') bot.name = request.json['bot']['name'] bot.description = request.json['bot']['description'] bot.staging = request.json DatabaseManager.commit() return jsonify(message='ok')
def update_broadcast(broadcast_id): """Update a broadcast.""" broadcast = get_account_broadcast_by_id(broadcast_id) try: broadcast_json = request.json broadcast_json['account_id'] = g.account.id parse_broadcast(broadcast_json, broadcast.id) except BroadcastUnmodifiableError: raise AppError(HTTPStatus.STATUS_CLIENT_ERROR, CustomError.ERR_WRONG_PARAM, 'Broadcast not modifiable') except Exception as e: logger.exception(e) raise AppError(HTTPStatus.STATUS_CLIENT_ERROR, CustomError.ERR_WRONG_PARAM, 'Broadcast update request failed') DatabaseManager.commit() return jsonify(message='ok')
def step(self, bot, user, user_input=None, input_vars=None): """Main function for executing a node.""" try: # pylint: disable=R0101 now = datetime.datetime.now() if user.session is None: if user_input: user_input.disable_jump() user.goto(Bot.START_STABLE_ID) g.user = user if user_input: if config.STORE_CONVERSATION: Conversation(bot_id=user.bot_id, user_id=user.id, sender_enum=SenderEnum.Human, msg=user_input).add() # Parse audio as text if there are audio payload user_input.ParseAudioAsText(user) user_input = user_input.RunInputTransformation() # If there was admin interaction, and admin_interaction_timeout # haven't reached yet, do not run engine. if (bot.admin_interaction_timeout > 0 and ((now - user.last_admin_seen).total_seconds() < bot.admin_interaction_timeout)): return # Check has been idle for too long, reset it's state if yes. if (bot.session_timeout > 0 and ((now - user.last_seen).total_seconds() > bot.session_timeout)): user.last_seen = datetime.datetime.now() user.goto(Bot.ROOT_STABLE_ID) if user_input and user_input.jump(): node = Node.get_by(stable_id=user_input.jump_node_id, bot_id=bot.id, single=True) # Check if the node belongs to current bot if node is None: logger.critical('Invalid jump node_id %s' % user_input.jump_node_id) # If payload button is pressed, we need to jump to the # corresponding node if payload's node_id != current_node_id elif user_input.jump_node_id != user.session.node_id: user.goto(user_input.jump_node_id) user.session.message_sent = True node = Node.get_by(stable_id=user.session.node_id, bot_id=bot.id, eager=['content_module', 'parser_module'], single=True) g.node = node if node is None: logger.critical('Invalid node_id %s' % user.session.node_id) user.goto(Bot.ROOT_STABLE_ID) user.session.message_sent = True return self.step(bot, user, user_input) track(TrackingInfo.Pageview(user.platform_user_ident, '/%s' % node.stable_id)) # Shared global variables global_variables = { 'user': user.to_json(), 'bot_id': bot.id } if not user.session.message_sent: env = { 'platform_type': SupportedPlatform( user.platform.type_enum.value) } # Prepare input variables input_vars = input_vars or {} input_vars.update(global_variables) # TODO(aitjcize): figure out how to deal with cm exceptions cm = node.content_module.get_module() # Send message messages = cm.run(node.content_config, env, input_vars) messaging.send_message(user, messages) user.session.message_sent = True # Store InputTransformation in session user.session.input_transformation = InputTransformation.get() if not node.expect_input: # There are no parser module, which means we are at end of # subgraph. if node.parser_module is None: user.goto(Bot.ROOT_STABLE_ID) user.session.message_sent = True return elif node.parser_module.id == PASSTHROUGH_MODULE_ID: return self.step(bot, user) else: raise RuntimeError('Node `%s\' with parser module ' 'not expecting input' % node) else: # We are already at root node and there is no user input. # Display root node again. if not user_input and node.stable_id == Bot.ROOT_STABLE_ID: user.session.message_sent = False return self.step(bot, user, user_input) # No parser module associate with this node, go back to root # node. if node.parser_module is None: user.goto(Bot.ROOT_STABLE_ID) user.session.message_sent = True # Run at root instead, so disable jump user_input.disable_jump() return self.step(bot, user, user_input) if (not user_input and node.parser_module.id != PASSTHROUGH_MODULE_ID): raise RuntimeError('no user input when running parser') result, variables = self.run_parser_module( node, user, user_input, global_variables, False) # Node parser failed, try root parser: if result.errored and node.stable_id != Bot.ROOT_STABLE_ID: root_result, root_variables = self.run_parser_module( bot.root_node, user, user_input, global_variables, True) # If root paser matched, use root_parser result as result. if not root_result.errored: result = root_result variables = root_variables if result.ack_message: self.send_ack_message(user, result.ack_message, variables) # end_node_id may be None, either there is a bug or parser # module decide not to move at all. if result.end_node_id: user.goto(result.end_node_id) # If we are going back the same node, assume there is an # error and we want to retry. don't send message in this # case. if (result.end_node_id == node.stable_id and node.stable_id != Bot.ROOT_STABLE_ID and result.skip_content_module): user.session.message_sent = True return else: # There is no link, replay current node. user.session.message_sent = False # Run next content module return self.step(bot, user, None, variables) except Exception as e: logger.exception(e) # Rollback when error happens, so user won't get stuck in some # weird state. DatabaseManager.rollback() finally: user.last_seen = datetime.datetime.now() DatabaseManager.commit()