示例#1
0
def start(update, context):
    """
    Shows welcome message and asks for language
    """
    try:
        # Try to answer query if the user is registering again
        update.callback_query.answer()
    except Exception:
        pass

    patient_id = update._effective_user.id
    # Check that user is not registered
    try:
        patient = Patient.objects.get(identifier=patient_id)
        logger.info(
            f'User {patient.username} tried to register again.')
        context.bot.send_message(chat_id=patient_id, text=messages[patient.language]['already_exists'])
        return ConversationHandler.END
    except Patient.DoesNotExist:
        # The user should not exist in DB
        context.user_data['patient'] = Patient(name=update._effective_user.first_name,
                                               identifier=str(patient_id),
                                               username=update._effective_user.username)

    logger.info(f'User {update._effective_user.username} started a new conversation')
    context.bot.send_message(chat_id=patient_id,
                             text=f'Hi {update._effective_user.first_name}. Welcome to HOW-R-U psychologist bot.\n'
                                  f'Hola {update._effective_user.first_name}. Bienvenido al bot psicólogo HOW-R-U')
    context.bot.send_message(chat_id=patient_id, text=f'Please select a language:\nElija un idioma por favor:',
                             reply_markup=keyboards.language_keyboard)

    return LANGUAGE
示例#2
0
def cancel(update, context):
    """
    Cancels current action and shows config menu
    """
    logger.info(
        f'User {update.message.from_user.username} cancelled current operation.')
    return config_menu(update, context)
示例#3
0
def finish(update, context):
    """
    Saves patient in DB, assigns him/her to data_analyst, creates PendingQuestion entries for assigned_to_all questions
    and finally creates the user's PendingQuestionJob
    """
    patient = context.user_data['patient']
    patient.save()
    # Add patient to data analysts and assigned_to_all questions
    try:
        data_analysts = Doctor.objects.filter(is_analyst=True)
        for doctor in data_analysts:
            patient.assigned_doctors.add(doctor)
            patient.save()
            assigned_to_all = doctor.assigned_questions.filter(assigned_to_all=True)
            for question in assigned_to_all:
                pending_question = PendingQuestion(doctor=doctor,
                                                   question=question,
                                                   patient=patient,
                                                   answering=False)
                pending_question.save()
        logger.info("Patient %s assigned to data_analysts", patient.username)
    except Exception:
        logger.exception("Exception while adding patient %s to data_analysts.", patient.username)
    update.message.reply_text(messages[patient.language]['registration_ok'])
    logger.info(f'Creating pending_questions job for user {update.message.from_user.username}')
    PendingQuestionJob(context, patient)
    return ConversationHandler.END
示例#4
0
 def job_callback(self, context):
     """
     Prompts PendingQuestions to the user.
     """
     pending_questions = self._get_pending_questions()
     for task in pending_questions:
         if not self.is_question_answered(task):
             question = task.question
             task.answering = True
             task.save()
             context.bot.send_message(
                 chat_id=self.patient.identifier,
                 text=question.text,
                 reply_markup=keyboards.get_custom_keyboard(
                     question.response_set.all()))
             while not self.is_question_answered(task):
                 time.sleep(0.5)
     message = messages[self.patient.language]['finish_answering'] if self.answered_questions_today() else \
         messages[self.patient.language]['no_questions']
     logger.info(f'User {self.patient.username} answered all the questions')
     context.bot.send_message(chat_id=self.patient.identifier,
                              text=message,
                              reply_markup=ReplyKeyboardRemove())
     time.sleep(0.1)
     if was_configurator_running(self.patient.identifier, context):
         logger.info(
             f'Reopening configurator for user {self.patient.username} id {self.patient.identifier}'
         )
         context.bot.send_message(
             chat_id=self.patient.identifier,
             text=messages[self.patient.language]['select_config'],
             reply_markup=keyboards.config_keyboard[self.patient.language])
示例#5
0
def answer_question(update, context):
    """
    Prompts user's question by querying PendingQuestion DB.
    Creates an AsweredQuestion object.
    """
    user = update.message.from_user
    response = update.message.text
    # Get question that is being answered from DB:
    try:
        question_task = _get_pending_question_task(str(user.id))
    except PendingQuestion.DoesNotExist:
        logger.info(
            f'User {user.username} id {user.id} wrote {response} while there was no question to answer'
        )
        update.message.reply_text(
            "Unrecognized command\nComando no reconocido",
            reply_markup=ReplyKeyboardRemove())
        return ConversationHandler.END
    logger.info(
        f'User {user.username} id {user.id} answered "{response}" to question "{question_task.question}"'
    )
    response_object = question_task.question.response_set.get(text=response)
    # Create answered question entry
    answered_question = AnsweredQuestion(patient_id=user.id,
                                         doctor=question_task.doctor,
                                         answer_date=datetime.now(
                                             pytz.timezone('Europe/Madrid')),
                                         response=response_object,
                                         question=question_task.question)
    answered_question.save()
    # Set answering to false
    question_task.answering = False
    question_task.save()

    return ConversationHandler.END
示例#6
0
def back(update, context):
    """
    Cancels current action and shows config menu
    """
    update.callback_query.answer()
    username = context.user_data["patient"].username
    logger.info(f'User {username} cancelled current operation.')
    return config_menu(update, context)
示例#7
0
def ask_delete_user(update, context):
    """
    Asks for confirmation to completely delete the user from the system.
    """
    patient = context.user_data['patient']
    logger.info(f'User {update.message.from_user.username} wants to delete his account.')
    update.message.reply_text(messages[patient.language]['delete_user'],
                              reply_markup=keyboards.delete_user_keyboard[patient.language])
    return PROCESS_DELETE_USER
示例#8
0
def _exit(update, context):
    """
    Exits from the configurator
    """
    patient = context.user_data['patient']
    logger.info(f'User {update.message.from_user.username} close the configurator.')
    update.message.reply_text(messages[patient.language]['exit_configurator'],
                              reply_markup=ReplyKeyboardRemove())
    return ConversationHandler.END
示例#9
0
def ask_change_name(update, context):
    """
    Sends old name to the user and asks for the new one
    """
    patient = context.user_data['patient']
    logger.info(f'User {update.message.from_user.username} asked to change name')
    update.message.reply_text(messages[patient.language]['current_name'] + patient.name)
    update.message.reply_text(messages[patient.language]['change_name'], reply_markup=ReplyKeyboardRemove())
    return PROCESS_NAME
示例#10
0
def schedule(update, context):
    """
    Processes schedule and calls finish() method
    """
    patient_schedule = update.message.text
    patient = context.user_data['patient']
    logger.info(f'User {update.message.from_user.username} chose schedule {patient_schedule}')
    patient.schedule = patient_schedule
    return finish(update, context)
示例#11
0
def ask_change_gender(update, context):
    """
    Sends old gender to the user and asks for the new one
    """
    patient = context.user_data['patient']
    logger.info(f'User {update.message.from_user.username} asked to change gender')
    update.message.reply_text(messages[patient.language]['current_gender'] + patient.gender)
    update.message.reply_text(messages[patient.language]['change_gender'],
                              reply_markup=keyboards.gender_keyboard[patient.language])
    return PROCESS_GENDER
示例#12
0
def process_language(update, context):
    """
    Saves the new language
    """
    patient = context.user_data['patient']
    patient.language = Flag.unflag(update.message.text)
    patient.save(update_fields=['language'])
    logger.info(f'User {update.message.from_user.username} changed language to {patient.language}')
    update.message.reply_text(messages[patient.language]['language_updated'])
    return config_menu(update, context)
示例#13
0
def get_utc_result(value, timezone='Europe/Madrid'):
    # Get full datetime
    dt = datetime.today()
    tmp = datetime.strptime(value, '%H:%M')
    dt = dt.replace(hour=tmp.hour, minute=tmp.minute, second=0)
    # Add timezone
    timezone = pytz.timezone(timezone)
    result = timezone.localize(dt)
    logger.info("el result %s", result)
    return result
示例#14
0
def process_delete_user(update, context):
    """
    Deletes the user from the system.
    """
    patient = context.user_data['patient']
    logger.info(f'User {update.message.from_user.username} deleted his account.')
    patient.delete()
    update.message.reply_text(messages[patient.language]['deleted_user'],
                              reply_markup=keyboards.start_keyboard)
    return ConversationHandler.END
示例#15
0
def ask_change_language(update, context):
    """
    Sends old language to the user and asks for the new one
    """
    patient = context.user_data['patient']
    logger.info(f'User {update.message.from_user.username} asked to change language')
    update.message.reply_text(messages[patient.language]['current_language'] + patient.language)
    update.message.reply_text(messages[patient.language]['change_language'],
                              reply_markup=keyboards.language_keyboard)
    return PROCESS_LANGUAGE
示例#16
0
def process_gender(update, context):
    """
    Saves the new gender
    """
    patient = context.user_data['patient']
    gender = update.message.text
    patient.gender = gender
    patient.save(update_fields=['_gender'])
    logger.info(f'User {update.message.from_user.username} changed gender to {gender}')
    update.message.reply_text(messages[patient.language]['gender_updated'])
    return config_menu(update, context)
示例#17
0
def timezone(update, context):
    """
    Gets the patient's timezone by analyzing the sent location
    """
    patient = context.user_data['patient']
    patient_timezone = Patient.get_timezone_from_location(update.message.location)
    logger.info(f'User {patient.username} choose timezone {patient_timezone}')
    patient.timezone = patient_timezone
    context.bot.send_message(chat_id=patient.identifier, text=messages[patient.language]['choose_schedule'],
                             reply_markup=ReplyKeyboardRemove())
    return SCHEDULE
示例#18
0
def _exit(update, context):
    """
    Exits from the configurator
    """
    patient = context.user_data['patient']
    logger.info(f'User {patient.username} close the configurator.')

    update.callback_query.answer()
    update.callback_query.edit_message_text(
        messages[patient.language]['exit_configurator'])
    return ConversationHandler.END
示例#19
0
def default_timezone(update, context):
    """
    Sets default timezone to a patient (Europe/Madrid)
    """
    update.callback_query.answer()
    patient = context.user_data['patient']
    logger.info(f'Set default timezone (Europe/Madrid) for user {patient.username}')
    patient.timezone = "Europe/Madrid"
    context.bot.send_message(chat_id=patient.identifier, text=messages[patient.language]['choose_schedule'],
                             reply_markup=ReplyKeyboardRemove())
    return SCHEDULE
示例#20
0
def ask_change_schedule(update, context):
    """
    Sends old schedule to the user and asks for the new one
    """
    patient = context.user_data['patient']
    logger.info(f'User {update.message.from_user.username} asked to change schedule')
    schedule_dt = UTCTime.to_locale(patient.schedule)
    schedule = schedule_dt.strftime("%H:%M")
    update.message.reply_text(messages[patient.language]['current_schedule'] + schedule)
    update.message.reply_text(messages[patient.language]['change_schedule'], reply_markup=ReplyKeyboardRemove())
    return PROCESS_SCHEDULE
示例#21
0
def skip_picture(update, context):
    """
    Sets default picture and asks for schedule
    """
    update.callback_query.answer()

    patient = context.user_data['patient']
    logger.info(f'User {patient.username} did not send a picture, using default')
    patient.picture = '/projects/how-r-u/chatbot/pics/default_profile_picture.png'
    context.bot.send_message(chat_id=patient.identifier, text=messages[patient.language]['choose_timezone'],
                             reply_markup=keyboards.send_location_keyboard[patient.language])
    return TIMEZONE
示例#22
0
def process_name(update, context):
    """
    Saves the new name
    """
    patient = context.user_data['patient']
    old_name = patient.name
    name = update.message.text
    patient.name = name
    patient.save(update_fields=['name'])
    logger.info(f'User {update.message.from_user.username} old name {old_name} changed name to {name}')
    update.message.reply_text(messages[patient.language]['name_updated'])
    return config_menu(update, context)
示例#23
0
def ask_delete_user(update, context):
    """
    Asks for confirmation to completely delete the user from the system.
    """
    update.callback_query.answer()
    patient = context.user_data['patient']
    logger.info(f'User {patient.username} wants to delete his account.')
    context.bot.send_message(
        chat_id=patient.identifier,
        text=messages[patient.language]['delete_user'],
        reply_markup=keyboards.delete_user_keyboard[patient.language])
    return PROCESS_DELETE_USER
示例#24
0
def process_name(update, context):
    """
    Saves the new name
    """
    patient = context.user_data['patient']
    old_name = patient.name
    name = update.message.text
    patient.name = name
    patient.save(update_fields=['name'])
    logger.info(
        f'User {patient.name} old name {old_name} changed name to {name}')
    context.bot.send_message(chat_id=patient.identifier,
                             text=messages[patient.language]['name_updated'])
    return config_menu(update, context)
示例#25
0
def main():
    logger.info("Started HOW-R-U psychologist")
    # Initialize bot
    updater = Updater(token=bot_config.TOKEN, use_context=True)
    dispatcher = updater.dispatcher
    handlers = [start_handler, config_handler, question_handler]
    # Add handlers to dispatcher
    for handler in handlers:
        dispatcher.add_handler(handler)
    # Add error callback
    dispatcher.add_error_handler(error_callback)
    # Start bot service
    updater.start_polling()
    updater.idle()
示例#26
0
def language(update, context):
    """
    Processes language and asks for gender
    """
    update.callback_query.answer()

    patient_language = update.callback_query.data
    patient = context.user_data['patient']
    logger.info(f'User {patient.username} chose language {patient_language}')

    context.user_data['patient'].language = patient_language
    context.bot.send_message(chat_id=patient.identifier, text=messages[patient.language]['choose_gender'],
                             reply_markup=keyboards.gender_keyboard[patient.language])
    return GENDER
示例#27
0
def process_profile_pic(update, context):
    """
    Saves the new profile picture
    """
    patient = context.user_data['patient']
    photo_file = update.message.photo[-1].get_file()
    pic_name = f'/opt/chatbot/chatbot/pics/{update.message.from_user.id}.jpg'
    photo_file.download(pic_name)
    patient.picture = pic_name
    patient.save()
    logger.info(f'User {update.message.from_user.username} changed profile picture')
    update.message.reply_text(messages[patient.language]['picture_updated'],
                              reply_markup=ReplyKeyboardRemove())
    return config_menu(update, context)
示例#28
0
def gender(update, context):
    """
    Processes gender and asks for picture
    """
    update.callback_query.answer()

    patient = context.user_data['patient']
    patient_gender = update.callback_query.data
    logger.info(
        f'User {patient.username} chose gender {patient_gender}')
    patient.gender = patient_gender
    context.bot.send_message(chat_id=patient.identifier, text=messages[patient.language]['choose_pic'],
                             reply_markup=keyboards.skip_keyboard[patient.language])
    return PICTURE
示例#29
0
def picture(update, context):
    """
    Processes picture and asks for schedule
    """
    patient = context.user_data['patient']
    photo_file = update.message.photo[-1].get_file()
    pic_name = f'/projects/how-r-u/chatbot/pics/{update.message.from_user.id}.jpg'
    photo_file.download(pic_name)
    patient.picture = pic_name
    os.remove(pic_name)
    logger.info(f'User {update.message.from_user.username} sent picture {pic_name}')
    context.bot.send_message(chat_id=patient.identifier, text=messages[patient.language]['choose_timezone'],
                             reply_markup=keyboards.send_location_keyboard[patient.language])
    return TIMEZONE
示例#30
0
def process_wrong_schedule(update, context):
    """
    Informs that the patient introduced a wrong schedule
    """
    patient = context.user_data['patient']
    text = update.message.text
    logger.info(
        f'User {patient.username} introduced an invalid schedule ({text})')
    context.bot.send_message(
        chat_id=patient.identifier,
        text=messages[patient.language]['invalid_schedule'].format(text),
        reply_markup=keyboards.back_keyboard[patient.language])

    return PROCESS_SCHEDULE