async def update_integration_token( request: IntegrationRequest, current_user: User = Security(Authentication.get_current_user_and_bot, scopes=ADMIN_ACCESS), ): """ Enable/disable/delete an integration. """ Authentication.update_integration_token(request.name, current_user.get_bot(), current_user.get_user(), int_status=request.status) return {"message": "Integration status updated!"}
async def get_integrations(current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS), ): """ List available integrations. """ return Response(data=list( IntegrationProcessor.get_integrations(current_user.get_bot())))
async def get_delete_history_logs(current_user: User = Security( Authentication.get_current_user_and_bot, scopes=ADMIN_ACCESS)): """ Get history deletion event logs. """ logs = list(HistoryDeletionLogProcessor.get_logs(current_user.get_bot())) return Response(data=logs)
async def visitor_hit_fallback(month: int = Query(default=1, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the number of times the agent hit a fallback (ie. not able to answer) to user queries """ fallback_action, nlu_fallback_action = DataUtility.load_fallback_actions( current_user.get_bot()) return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/metrics/fallback', { 'month': month, 'action_fallback': fallback_action, 'nlu_fallback': nlu_fallback_action })
async def fallback_trend(month: int = Query(default=6, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the fallback count of the bot for previous months """ fallback_action, nlu_fallback_action = DataUtility.load_fallback_actions( current_user.get_bot()) return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/trends/fallback', { 'month': month, 'action_fallback': fallback_action, 'nlu_fallback': nlu_fallback_action })
async def allow_bot_for_user( allow_bot: BotAccessRequest, background_tasks: BackgroundTasks, bot: str = Path(default=None, description="bot id", example="613f63e87a1d435607c3c183"), current_user: User = Security(Authentication.get_current_user_and_bot, scopes=ADMIN_ACCESS)): """ Allows user to access a bot. """ bot_name, url = AccountProcessor.allow_bot_and_generate_invite_url( bot, allow_bot.email, current_user.get_user(), current_user.account, allow_bot.role) if Utility.email_conf["email"]["enable"]: background_tasks.add_task( Utility.format_and_send_mail, mail_type='add_member', email=allow_bot.email, url=url, first_name=f'{current_user.first_name} {current_user.last_name}', bot_name=bot_name, role=allow_bot.role) return Response(message='An invitation has been sent to the user') else: return {"message": "User added"}
async def fallback_dropoff(month: int = Query(default=1, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the list of users that dropped off after encountering fallback """ fallback_action, nlu_fallback_action = DataUtility.load_fallback_actions( current_user.get_bot()) return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/metrics/fallback/dropoff', { 'month': month, 'action_fallback': fallback_action, 'nlu_fallback': nlu_fallback_action })
async def unsuccessful_session_count( month: int = Query(default=1, ge=1, le=6), current_user: User = Security(Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the count of sessions that encountered a fallback for a particular user. """ fallback_action, nlu_fallback_action = DataUtility.load_fallback_actions( current_user.get_bot()) return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/metrics/sessions/unsuccessful', { 'month': month, 'action_fallback': fallback_action, 'nlu_fallback': nlu_fallback_action })
async def complete_conversations(month: int = Query(default=1, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the number of successful conversations of the bot, which had no fallback """ fallback_action, nlu_fallback_action = DataUtility.load_fallback_actions( current_user.get_bot()) return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/metrics/conversation/success', { 'month': month, 'action_fallback': fallback_action, 'nlu_fallback': nlu_fallback_action })
async def add_bot(request: TextData, current_user: User = Depends( Authentication.get_current_user)): """ Add new bot in a account. """ AccountProcessor.add_bot(request.data, current_user.account, current_user.get_user()) return {'message': 'Bot created'}
async def get_users_details(current_user: User = Depends( Authentication.get_current_user)): """ returns the details of the current logged-in user """ user_details = AccountProcessor.get_user_details_and_filter_bot_info_for_integration_user( current_user.email, current_user.is_integration_user, current_user.get_bot()) return {"data": {"user": user_details}}
def wrapped(current_user: User, **kwargs): today = datetime.today() today_start = today.replace(hour=0, minute=0, second=0) account = Account.objects().get(id=current_user.account) limit = account.license['training'] if "training" in account.license else Utility.environment['model']['train'][ "limit_per_day"] count = ModelTraining.objects(bot=current_user.get_bot(), start_timestamp__gte=today_start).count() if count >= limit: raise AppException("Training limit exhausted!")
async def feedback(request_data: FeedbackRequest, current_user: User = Depends( Authentication.get_current_user)): """ Receive feedback from user. """ AccountProcessor.add_feedback(request_data.rating, current_user.get_user(), request_data.scale, request_data.feedback) return {"message": "Thanks for your feedback!"}
async def update_ui_config(request_data: DictData, current_user: User = Depends( Authentication.get_current_user)): """ Add/update ui configuration for user. """ AccountProcessor.update_ui_config(request_data.data, current_user.get_user()) return {"message": "Config saved!"}
async def list_active_bot_invites(current_user: User = Security( Authentication.get_current_user)): """ Lists active bot invites. """ return Response( data={ 'active_invites': list(AccountProcessor.list_active_invites(current_user.get_user())) })
async def conversation_time(month: int = Query(default=1, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the duration of the chat that took place between the users and the agent""" return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/metrics/conversation/time', {'month': month})
async def delete_bot_conversations_history( background_tasks: BackgroundTasks, month: int = Query(default=3, ge=1, le=6), current_user: User = Security(Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Deletes bot chat history for all users up to certain months min 1 month max 6 months """ HistoryDeletionLogProcessor.is_event_in_progress( bot=current_user.get_bot()) ChatHistoryUtils.validate_history_endpoint(bot=current_user.get_bot()) background_tasks.add_task(EventsTrigger.trigger_history_deletion, bot=current_user.get_bot(), user=current_user.get_user(), month=month) return { "message": "Delete chat history initiated. It may take a while. Check logs!" }
async def calculate_retention(month: int = Query(default=1, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the user retention percentage of the bot """ return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/metrics/users/retention', {'month': month})
async def flat_conversations(month: int = Query(default=1, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the flattened conversation data of the bot for previous months """ return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/conversations/', {'month': month})
async def list_bots(current_user: User = Depends( Authentication.get_current_user)): """ List bots for account. """ bots = AccountProcessor.get_accessible_bot_details(current_user.account, current_user.email) if current_user.is_integration_user: bots = Utility.filter_bot_details_for_integration_user( current_user.get_bot(), bots) return Response(data=bots)
async def user_intent_dropoff(month: int = Query(default=1, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the identified intents and their counts for users before dropping off from the conversations. """ return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/metrics/intents/dropoff', {'month': month})
async def user_input_unique( month: int = Query(default=1, ge=1, le=6), current_user: User = Security(Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS), ): """ Returns the list of user inputs that are not included as part of training examples """ queries_not_present = ChatHistoryUtils.unique_user_input( month, current_user.get_bot()) return Response(data=queries_not_present)
async def conversation_time_trend(month: int = Query(default=6, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the average conversation time of the bot for previous months """ return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/trends/conversations/time', {'month': month})
async def total_sessions(month: int = Query(default=1, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the total session count for users for the past months. """ return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/metrics/sessions/total', {'month': month})
async def user_with_metrics(month: int = Query(default=1, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the list of user who has conversation with the agent with steps anf time """ return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/metrics/users', {'month': month})
async def count_new_users(month: int = Query(default=1, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the number of new users of the bot """ return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/metrics/users/new', {'month': month})
async def chat_history(sender: Text, month: int = Query(default=1, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Fetches the list of conversation with the agent by particular user """ return Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/conversations/users/{sender}', {'month': month})
async def delete_user_chat_history(background_tasks: BackgroundTasks, sender: Text, month: int = Query(default=3, ge=1, le=6), current_user: User = Security( Authentication.get_current_user_and_bot, scopes=ADMIN_ACCESS)): """ Deletes user chat history up to certain months min 3 month max 6 months """ HistoryDeletionLogProcessor.is_event_in_progress( bot=current_user.get_bot()) ChatHistoryUtils.validate_history_endpoint(bot=current_user.get_bot()) background_tasks.add_task(EventsTrigger.trigger_history_deletion, bot=current_user.get_bot(), user=current_user.get_user(), month=month, sender_id=sender) return { "message": "Delete user history initiated. It may take a while. Check logs!" }
def get_user_from_token(token: Text, request: HTTPServerRequest, **kwargs): """ validates jwt token :param token: jwt token :param request: http request object :return: dict of user details """ credentials_exception = ServiceHandlerException( "Could not validate credentials", 401, {"WWW-Authenticate": "Bearer"}) try: payload = Utility.decode_limited_access_token(token) username: str = payload.get("sub") TornadoAuthenticate.validate_limited_access_token( request, payload.get("access-limit")) if username is None: raise credentials_exception except PyJWTError: raise credentials_exception user = AccountProcessor.get_user_details(username) if user is None: raise credentials_exception user_model = User(**user) if payload.get("type") != TOKEN_TYPE.LOGIN.value: TornadoAuthenticate.validate_bot_request(kwargs.get('bot'), payload.get('bot')) if payload.get("type") == TOKEN_TYPE.INTEGRATION.value: TornadoAuthenticate.validate_integration_token(payload) alias_user = request.headers.get("X-USER") if Utility.check_empty_string(alias_user) and payload.get( "type") == TOKEN_TYPE.INTEGRATION.value: raise ServiceHandlerException( "Alias user missing for integration", 401) alias_user = alias_user or username user_model.alias_user = alias_user user_model.is_integration_user = True user_model.role = payload.get('role') return user_model
async def download_conversations( month: int = Query(default=1, ge=1, le=6), current_user: User = Security(Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS), ): """ Downloads conversation history of the bot, for the specified months """ response = Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/conversations/download', {'month': month}, return_json=False) bot_name = [ bot['name'] for bot in AccountProcessor.list_bots(current_user.account) if bot['_id'] == current_user.get_bot() ][0] response.headers[ "Content-Disposition"] = f"attachment; filename=conversation_history_{bot_name}{datetime.date.today().strftime('_%d_%m_%y.csv')}" return StreamingResponse(BytesIO(response.content), headers=response.headers)