def is_correct_replier(self, bot, message): question_replier = QuestionReplier.get_by_message_id( self._session, message.id) # get repliers in this level filtered_question_repliers = [ x for x in question_replier.question.question_repliers if x.replier.level_id == question_replier.replier.level_id ] # set status to replying if message is sent without clicking the buttom # (has refused or still in knowledge validation) if all(x.reply_status_id == 1 or x.reply_status_id == 2 for x in filtered_question_repliers): self.set_status_for_repliers(filtered_question_repliers, question_replier) self._session.flush() if question_replier.reply_status_id != 3: slack_user_id = question_replier.message.slack_user_id replier = Replier.get_replier_by_slack_id(self._session, slack_user_id) channel_id = replier.channel_id if question_replier.reply_status_id == 6: bot.post_message(channel_id, GAVE_UP_RESPONDING_MESSAGE, question_replier.message.slack_message_id) else: bot.post_message(channel_id, ANOTHER_REPLIER_ANSWERING_QUESTION, question_replier.message.slack_message_id) return False # if question_replier.reply_status_id == 3 return True
def validation_keep_answering_or_not(self, action): """If the replier wants to keep answering the question""" if action.value == 'no': message = Message.get_message(self._session, action.message_id, action.slack_user_id) question_replier = QuestionReplier.get_by_message_id( self._session, message.id) question_replier.reply_status_id = 6 self._session.add(question_replier) channel_id, message_id, replier_question_id = self.get_expert_info_to_reply( message) channel_id_student, _, _ = self.get_user_info_to_reply(message) self.delete_previous_scheduled_messages(action.bot, channel_id, replier_question_id, 1) self.delete_previous_scheduled_messages(action.bot, channel_id, replier_question_id, 2) self.delete_previous_scheduled_messages(action.bot, channel_id_student, replier_question_id, 4) # send question to another level since the replier doesn't want to keep answering filtered_question_repliers = [x for x in question_replier.question.question_repliers \ if x.replier.level_id == question_replier.replier.level_id] for qr in filtered_question_repliers: self.delete_previous_scheduled_messages( action.bot, qr.replier.channel_id, qr.id, 3) self.go_to_next_level(action)
def get_question_id_message(self, message): if message.is_replier_message: question_replier = QuestionReplier.get_by_message_id( self._session, message.id) question = Question.get_question_id(self._session, question_replier.question_id) else: question = Question.get_question(self._session, message.id) return question.id
def _is_resolved(self, message): """Check whether the question has been marked as resolved or not""" if message.is_replier_message: question_replier = QuestionReplier.get_by_message_id( self._session, message.id) question_is_resolved = question_replier.question.is_resolved else: question = Question.get_question(self._session, message.id) question_is_resolved = question.is_resolved return question_is_resolved
def add_question_replier_to_db(self, question, question_replier): """Add just a question replier to database. :type question: Question :type question_replier: tuple[Replier, str] :rtype: QuestionReplier """ day = datetime.now().strftime("%d/%m/%Y, %H:%M:%S") message = Message(slack_user_id=question_replier[0].slack_id, slack_message_id=question_replier[1], is_replier_message=True, date=day) new_question = QuestionReplier(reply_status_id=1) new_question.replier = question_replier[0] new_question.message = message new_question.question = question self._session.add_all([message, new_question]) return new_question
def get_expert_info_to_reply(self, message): if message.is_replier_message: question_replier = QuestionReplier.get_by_message_id( self._session, message.id) else: question = Question.get_question(self._session, message.id) question_replier = next((x for x in question.question_repliers if x.reply_status_id == 3)) user_id = question_replier.message.slack_user_id message_id = question_replier.message.slack_message_id channel_id = question_replier.replier.channel_id return channel_id, message_id, question_replier.id
def reply_question(self, event): """Handle messages that are sent to existing thread""" message = Message.get_message(self._session, event.thread_id, event.user) if self._is_resolved(message): self.send_closed_message(event, message) return if message.is_replier_message: question_replier = QuestionReplier.get_by_message_id( self._session, message_id=message.id) question = Question.get_question_id( self._session, question_id=question_replier.question_id) if not self.is_correct_replier(event.bot, message): return channel_id, message_id, replier_question_id = self.get_user_info_to_reply( message) self.delete_previous_scheduled_messages(event.bot, event.channel, replier_question_id, 3) event.bot.delete_message_in_history( event.channel, event.thread_id, [ WANT_ANSWER_QUESTION, WANT_CONTINUE_RESPONDING, M_ASKS_REPLIER_CLOSE_QUESTION ]) attachments_type = '' else: question = Question.get_question(self._session, message_id=message.id) channel_id, message_id, _ = self.get_expert_info_to_reply(message) attachments_type = ATTACHMENTS_keep_answering_or_not event.bot.delete_message_in_history(event.channel, event.thread_id, [QUESTION_ANSWERED]) message_txt = WANT_CONTINUE_RESPONDING # if this question has continous messages if question.new_message_user == 1: # add some text as alert in order to avoid this behaviour again event.bot.post_message( channel_id, USER_ALERT + question.message_text + '\n\n' + USER_ALERT_2, message_id, attachments_type) self._session.query(Question).filter_by(id=question.id).update( {'new_message_user': 0}) event.bot.post_message(channel_id, event.message_text, message_id) if attachments_type != '': event.bot.post_message(channel_id, message_txt, message_id, attachments_type) self.handle_scheduled_message(event, message)
def get_user_info_to_reply(self, message): if message.is_replier_message: question_replier = QuestionReplier.get_by_message_id( self._session, message.id) user_id = question_replier.question.message.slack_user_id message_id = question_replier.question.message.slack_message_id question_replier_id = question_replier.id else: question = Question.get_question(self._session, message.id) user_id = question.message.slack_user_id message_id = question.message.slack_message_id question_replier_id = None replier = Replier.get_replier_by_slack_id(self._session, user_id) channel_id = replier.channel_id return channel_id, message_id, question_replier_id
def handle_scheduled_message(self, event, message): """Schedule messages to close question by inactivity""" channel_id, message_id, replier_question_id = self.get_expert_info_to_reply( message) question_replier = QuestionReplier.get_by_id(self._session, replier_question_id) # get the students' info channel_id_student, message_id_student, _ = self.get_user_info_to_reply( message) # deleting previous scheduled messages self.delete_previous_scheduled_messages(event.bot, channel_id, replier_question_id, 1) self.delete_previous_scheduled_messages(event.bot, channel_id, replier_question_id, 2) self.delete_previous_scheduled_messages(event.bot, channel_id_student, replier_question_id, 4) # scheduling new messages sch_message_id = event.bot.schedule_message( channel_id, M_ASKS_REPLIER_CLOSE_QUESTION, TIMEOUT_CLOSE_QUESTION_REPLIER, message_id, attachments=ATTACHMENTS_close_question_validation) self.add_scheduled_message_to_db(sch_message_id, question_replier, 1) sch_message_id = event.bot.schedule_message( channel_id, M_VALIDATION_CLOSED_QUESTION, TIMEOUT_CLOSE_QUESTION_NOT_RESPONSE, message_id) self.add_scheduled_message_to_db(sch_message_id, question_replier, 2) sch_message_id = event.bot.schedule_message( channel_id_student, QUESTION_ANSWERED, TIMEOUT_CLOSE_QUESTION_STUDENT, message_id_student, attachments=ATTACHMENTS_answer_validation_after_reply) self.add_scheduled_message_to_db(sch_message_id, question_replier, 4)
def handle_knowledge_validation(self, action): """If a replier wants or not to answer the first question""" message = Message.get_message(self._session, action.message_id, action.slack_user_id) question_replier = QuestionReplier.get_by_message_id( self._session, message.id) replier_level_id = question_replier.replier.level_id if question_replier.reply_status_id == 3: return all_question_repliers = question_replier.question.question_repliers filtered_question_repliers = [x for x in all_question_repliers \ if x.replier.level_id == replier_level_id] # inform to a replier that another replier is already anwering the question if next( (x for x in filtered_question_repliers if x.reply_status_id == 3), None): action.bot.post_message(action.channel_id, ANOTHER_REPLIER_ANSWERING_QUESTION, action.message_id) return if action.value == 'yes': for qr in filtered_question_repliers: self.delete_previous_scheduled_messages( action.bot, qr.replier.channel_id, qr.id, 3) self.set_status_for_repliers(filtered_question_repliers, question_replier) return if action.value == 'no': self.handle_no_knowledge_validation(action, filtered_question_repliers, question_replier)
def go_to_next_level(self, event): """Prepares what is necessary to go up to the next level in 3 cases: 1. All users at some level ignore the question. 2. All users at some level reject to answer. 3. A replier stop answering. """ try: # case 1 message = Message.get_message_by_thread(self._session, event.thread_id) question_replier = QuestionReplier.get_by_message_id( self._session, message.id) except: try: # just for "action" on 'handle_knowledge_validation' and 'validation_keep_answering_or_not' (case 2 & 3) message = Message.get_message(self._session, event.message_id, event.slack_user_id) question_replier = QuestionReplier.get_by_message_id( self._session, message.id) except: return level_id = question_replier.replier.level_id next_level_id = ReplierLevel.get_next_lvl_id(self._session, level_id).next_level_id print("From level {} to {}. Number of Loop: {}".format( level_id, next_level_id, question_replier.question.number_of_loops)) question_repliers = question_replier.question.question_repliers question_date = question_replier.question.message_date question_level_id = question_replier.question.level # validate if we are on the right level if level_id == question_level_id: # update question's level on db question_replier.question.level += 1 # update status of repliers as "passou" for x in [ question_replier for question_replier in question_repliers if question_replier.reply_status_id == 1 ]: x.reply_status_id = 4 # if there are not more repliers already if all(question_replier.reply_status_id != 3 for question_replier in question_repliers): original_message = question_replier.question.message history_text = self.save_message_history(event.bot, question_replier.id, next_level=True) # we are going to the next loop if next_level_id == 1: print("Going to next loop...") question_replier.question.number_of_loops += 1 question_replier.question.level = 1 # reset the level # for more than 2 loops, send a message to monitors if question_replier.question.number_of_loops > 2: message_id_user = question_replier.question.message_id message_user = Message.get_message_by_id( self._session, message_id=message_id_user) user = Replier.get_replier_by_slack_id( self._session, slack_id=message_user.slack_user_id) send_email( '*****@*****.**', 'Dúvida do aluno: \n' + question_replier.question.message_text + '\n\n' + 'Informações do aluno: \n' + 'Slack_id: ' + user.slack_id + '\n' + 'E-mail: ' + user.email + '\n' + 'Data e hora: ' + question_date + '\n', 'Dúvida não respondida - ExperIA - ' + question_date) self.save_message_history(event.bot, question_replier.id) return new_question_repliers = self.forward_first_message( event.bot, history_text, next_level_id, original_message.slack_user_id) db_question_repliers = self.add_question_repliers_to_db( question_replier.question, new_question_repliers) self.time_to_level_up(event.bot, db_question_repliers) filtered_question_repliers = [x for x in question_repliers \ if x.replier.level_id == question_replier.replier.level_id and \ x.replier.id != question_replier.replier.id] for qr in filtered_question_repliers: event.bot.post_message(qr.replier.channel_id, M_EXPIRATION_TIME + ' ', qr.message.slack_message_id) event.bot.delete_message_in_history( qr.replier.channel_id, qr.message.slack_message_id, [WANT_ANSWER_QUESTION]) self._session.add_all(question_repliers)