def get_exp_thread_summaries(user_id, thread_ids): """Returns a list of summaries corresponding to the exploration threads from the given thread ids. Non-exploration threads are not included in the list. It also returns the number of threads that are currently not read by the user. Args: user_id: str. The id of the user. thread_ids: list(str). The ids of the threads for which we have to fetch the summaries. Returns: tuple(thread_summaries, number_of_unread_threads). Where: thread_summaries: list(FeedbackThreadSummary). number_of_unread_threads: int. The number of threads not read by the user. """ # We need to fetch the thread models first to filter out the threads which # don't refer to an exploration. exp_thread_models = [ model for model in feedback_models.GeneralFeedbackThreadModel.get_multi(thread_ids) if model and model.entity_type == feconf.ENTITY_TYPE_EXPLORATION ] exp_thread_user_model_ids = [ feedback_models.GeneralFeedbackThreadUserModel.generate_full_id( user_id, model.id) for model in exp_thread_models ] exp_model_ids = [model.entity_id for model in exp_thread_models] exp_thread_user_models, exp_models = ( datastore_services.fetch_multiple_entities_by_ids_and_models([ ('GeneralFeedbackThreadUserModel', exp_thread_user_model_ids), ('ExplorationModel', exp_model_ids), ])) threads = [_get_thread_from_model(m) for m in exp_thread_models] flattened_last_two_message_models_of_threads = ( feedback_models.GeneralFeedbackMessageModel.get_multi( itertools.chain.from_iterable(t.get_last_two_message_ids() for t in threads))) last_two_message_models_of_threads = [ flattened_last_two_message_models_of_threads[i:i + 2] for i in python_utils.RANGE( 0, len(flattened_last_two_message_models_of_threads), 2) ] thread_summaries = [] number_of_unread_threads = 0 for thread, last_two_message_models, thread_user_model, exp_model in ( python_utils.ZIP(threads, last_two_message_models_of_threads, exp_thread_user_models, exp_models)): message_ids_read_by_user = (() if thread_user_model is None else thread_user_model.message_ids_read_by_user) last_message_model, second_last_message_model = last_two_message_models # We don't need to check if the last message is None because all threads # have at least one message. last_message_is_read = (last_message_model.message_id in message_ids_read_by_user) author_last_message = (last_message_model.author_id and user_services.get_username( last_message_model.author_id)) # The second-to-last message, however, might be None. second_last_message_is_read = (second_last_message_model is not None and second_last_message_model.message_id in message_ids_read_by_user) author_second_last_message = (second_last_message_model and second_last_message_model.author_id and user_services.get_username( second_last_message_model.author_id)) if not last_message_is_read: number_of_unread_threads += 1 thread_summaries.append( feedback_domain.FeedbackThreadSummary( thread.status, thread.original_author_id, thread.last_updated, last_message_model.text, thread.message_count, last_message_is_read, second_last_message_is_read, author_last_message, author_second_last_message, exp_model.title, exp_model.id, thread.id)) return thread_summaries, number_of_unread_threads
def get_thread_summaries(user_id, thread_ids): """Returns a list of summaries corresponding to each of the threads given. It also returns the number of threads that are currently not read by the user. Args: user_id: str. The id of the user. thread_ids: list(str). The ids of the threads for which we have to fetch the summaries. Returns: tuple(thread_summaries, number_of_unread_threads), where: thread_summaries: list(FeedbackThreadSummary). number_of_unread_threads: int. The number of threads not read by the user. """ thread_user_ids = [ feedback_models.GeneralFeedbackThreadUserModel.generate_full_id( user_id, thread_id) for thread_id in thread_ids ] thread_exp_ids = [ get_exp_id_from_thread_id(thread_id) for thread_id in thread_ids ] thread_models, thread_user_models, thread_exp_models = ( datastore_services.fetch_multiple_entities_by_ids_and_models([ ('GeneralFeedbackThreadModel', thread_ids), ('GeneralFeedbackThreadUserModel', thread_user_ids), ('ExplorationModel', thread_exp_ids), ])) threads = [_get_thread_from_model(m) for m in thread_models] flat_last_two_message_models = ( feedback_models.GeneralFeedbackMessageModel.get_multi( itertools.chain.from_iterable(t.get_last_two_message_ids() for t in threads))) last_two_message_models_of_threads = [ flat_last_two_message_models[i:i + 2] for i in python_utils.RANGE(0, len(flat_last_two_message_models), 2) ] thread_summaries = [] number_of_unread_threads = 0 for thread, last_two_message_models, user_model, exp_model in ( python_utils.ZIP(threads, last_two_message_models_of_threads, thread_user_models, thread_exp_models)): last_message_model, second_last_message_model = last_two_message_models message_ids_read_by_user = (() if user_model is None else user_model.message_ids_read_by_user) # The last message is never None because all threads have at least one # message. last_message_is_read = (last_message_model.message_id in message_ids_read_by_user) author_last_message = (last_message_model.author_id and user_services.get_username( last_message_model.author_id)) # The second-to-last message, however, can be None. second_last_message_is_read = (second_last_message_model is not None and second_last_message_model.message_id in message_ids_read_by_user) author_second_last_message = (second_last_message_model and second_last_message_model.author_id and user_services.get_username( second_last_message_model.author_id)) if not last_message_is_read: number_of_unread_threads += 1 thread_summaries.append( feedback_domain.FeedbackThreadSummary( thread.status, thread.original_author_id, thread.last_updated, last_message_model.text, thread.message_count, last_message_is_read, second_last_message_is_read, author_last_message, author_second_last_message, exp_model.title, exp_model.id, thread.id)) return thread_summaries, number_of_unread_threads