Example #1
0
def create_message(
        exploration_id, thread_id, author_id, updated_status, updated_subject,
        text):
    """Creates a new message for the thread and subscribes the author to the
    thread.

    Returns False if the message with the ID already exists.
    """
    from core.domain import event_services
    # Get the thread at the outset, in order to check that the thread_id passed
    # in is valid.
    full_thread_id = (
        feedback_models.FeedbackThreadModel.generate_full_thread_id(
            exploration_id, thread_id))
    thread = feedback_models.FeedbackThreadModel.get(full_thread_id)

    message_id = feedback_models.FeedbackMessageModel.get_message_count(
        exploration_id, thread_id)
    msg = feedback_models.FeedbackMessageModel.create(
        exploration_id, thread_id, message_id)
    msg.thread_id = full_thread_id
    msg.message_id = message_id
    msg.author_id = author_id
    if updated_status:
        if message_id == 0:
            # New thread.
            event_services.FeedbackThreadCreatedEventHandler.record(
                thread.exploration_id)
        else:
            # Thread status changed.
            event_services.FeedbackThreadStatusChangedEventHandler.record(
                thread.exploration_id, thread.status, updated_status)

        msg.updated_status = updated_status
    if updated_subject:
        msg.updated_subject = updated_subject
    msg.text = text
    msg.put()

    # We do a put() even if the status and subject are not updated, so that the
    # last_updated time of the thread reflects the last time a message was
    # added to it.
    if message_id != 0 and (updated_status or updated_subject):
        if updated_status and updated_status != thread.status:
            thread.status = updated_status
        if updated_subject and updated_subject != thread.subject:
            thread.subject = updated_subject
    thread.put()

    if (user_services.is_user_registered(author_id) and len(text) > 0 and
            feconf.CAN_SEND_EMAILS_TO_USERS and
            feconf.CAN_SEND_FEEDBACK_MESSAGE_EMAILS):
            # send feedback message email if user is registered.
        add_message_to_email_buffer(
            author_id, exploration_id, thread_id, message_id)

    if author_id:
        subscription_services.subscribe_to_thread(author_id, full_thread_id)

    return True
Example #2
0
def get_all_thread_participants(exploration_id, thread_id):
    """Fetches all participants of the given thread.

    Args:
        exploration_id: str.
        thread_id: str.

    Returns:
        set(str). A set containing all author_ids of participants in the thread.
    """
    return set([m.author_id for m in get_messages(exploration_id, thread_id)
                if user_services.is_user_registered(m.author_id)])
Example #3
0
def create_message(
        exploration_id, thread_id, author_id, updated_status, updated_subject,
        text, received_via_email=False):
    """Creates a new message for the thread and subscribes the author to the
    thread.

    Args:
        exploration_id: str. The exploration id the thread belongs to.
        thread_id: str. The thread id the message belongs to.
        author_id: str. The author id who creates this message.
        updated_status: str, one of STATUS_CHOICES. New thread status.
            Must be supplied if this is the first message of a thread. For the
            rest of the thread, should exist only when the status changes.
        updated_subject: str. New thread subject. Must be supplied if this is
            the first message of a thread. For the rest of the thread, should
            exist only when the subject changes.
        text: str. The text of the feedback message. This may be ''.
        received_via_email: bool. Whether new message is received via email or
            web.
    """
    from core.domain import event_services
    # Get the thread at the outset, in order to check that the thread_id passed
    # in is valid.
    full_thread_id = (
        feedback_models.FeedbackThreadModel.generate_full_thread_id(
            exploration_id, thread_id))
    thread = feedback_models.FeedbackThreadModel.get(full_thread_id)

    message_id = feedback_models.FeedbackMessageModel.get_message_count(
        exploration_id, thread_id)
    msg = feedback_models.FeedbackMessageModel.create(
        exploration_id, thread_id, message_id)
    msg.thread_id = full_thread_id
    msg.message_id = message_id
    msg.author_id = author_id
    if updated_status:
        if message_id == 0:
            # New thread.
            event_services.FeedbackThreadCreatedEventHandler.record(
                thread.exploration_id)
        else:
            # Thread status changed.
            event_services.FeedbackThreadStatusChangedEventHandler.record(
                thread.exploration_id, thread.status, updated_status)

        msg.updated_status = updated_status
    if updated_subject:
        msg.updated_subject = updated_subject
    msg.text = text
    msg.received_via_email = received_via_email
    msg.put()

    # We do a put() even if the status and subject are not updated, so that the
    # last_updated time of the thread reflects the last time a message was
    # added to it.
    old_status = thread.status
    if message_id != 0 and (updated_status or updated_subject):
        if updated_status and updated_status != thread.status:
            thread.status = updated_status
        if updated_subject and updated_subject != thread.subject:
            thread.subject = updated_subject
    new_status = thread.status
    thread.put()

    if (user_services.is_user_registered(author_id) and
            feconf.CAN_SEND_EMAILS and
            feconf.CAN_SEND_FEEDBACK_MESSAGE_EMAILS):
            # send feedback message email if user is registered.
        _add_message_to_email_buffer(
            author_id, exploration_id, thread_id, message_id, len(text),
            old_status, new_status)

    if author_id:
        subscription_services.subscribe_to_thread(author_id, full_thread_id)
Example #4
0
def create_messages(
        thread_ids, author_id, updated_status, updated_subject, text,
        received_via_email=False):
    """Creates a new message for each of the distinct threads in thread_ids and
    for each message, subscribes the author to the thread.

    Args:
        thread_ids: list(str). The thread ids to append the messages to.
        author_id: str. The id of the author who creates the messages.
        updated_status: str|None. One of STATUS_CHOICES. Applied to each thread.
            Must be supplied if this is the first message of the threads.
            Otherwise, this property should only exist when the status
            changes.
        updated_subject: str|None. New thread subject. Applied to each thread.
            Must be supplied if this is the first message of the threads.
            Otherwise, this property should only exist when the subject changes.
        text: str. The text of the feedback message. This may be ''.
        received_via_email: bool. Whether the new message(s) are received via
            email or web.

    Returns:
        list(FeedbackMessage). The domain objects representing the new messages
        added in the datastore.

    Raises:
        Exception. Thread_ids must be distinct.
        Exception. One or more GeneralFeedbackThreadModel entities not found.
    """
    from core.domain import event_services

    # Check that the thread_ids are distinct.
    if len(set(thread_ids)) != len(thread_ids):
        raise Exception(
            'Thread ids must be distinct when calling create_messsages.')

    # Get the threads at the outset, in order to check that there are models
    # corresponding to each of the thread_ids.
    thread_models = feedback_models.GeneralFeedbackThreadModel.get_multi(
        thread_ids)
    thread_ids_that_do_not_have_models = []
    for index, thread_model in enumerate(thread_models):
        if thread_model is None:
            thread_ids_that_do_not_have_models.append(thread_ids[index])
    if len(thread_ids_that_do_not_have_models) > 0:
        multiple_thread_models_are_missing = (
            len(thread_ids_that_do_not_have_models) > 1
        )
        raise Exception(
            'Thread%s belonging to the GeneralFeedbackThreadModel class with '
            'id%s:[%s] %s not found.' % (
                's' if multiple_thread_models_are_missing else '',
                's' if multiple_thread_models_are_missing else '',
                ' '.join(thread_ids_that_do_not_have_models),
                'were' if multiple_thread_models_are_missing else 'was'
            )
        )

    # Get the corresponding message ids, which are required for message
    # creation.
    message_ids = (
        feedback_models.GeneralFeedbackMessageModel.get_message_counts(
            thread_ids)
    )

    # Create a list of FullyQualifiedMessageIdentifier objects so that each
    # (thread_id, message_id) pair is kept together.
    message_identifiers = []
    for thread_id, message_id in python_utils.ZIP(thread_ids, message_ids):
        message_identifiers.append(
            feedback_domain.FullyQualifiedMessageIdentifier(
                thread_id, message_id))

    # Create the GeneralFeedbackMessageModel instances.
    message_models = feedback_models.GeneralFeedbackMessageModel.create_multi(
        message_identifiers)

    # Update the message instances.
    for index, message_model in enumerate(message_models):
        message_model.thread_id = thread_ids[index]
        message_model.message_id = message_ids[index]
        message_model.author_id = author_id
        message_model.text = text
        message_model.received_via_email = received_via_email
        # Get the corresponding thread in storage.
        thread_model = thread_models[index]
        if updated_status:
            message_model.updated_status = updated_status
            if message_model.message_id == 0:
                # New thread.
                if thread_model.entity_type == feconf.ENTITY_TYPE_EXPLORATION:
                    event_services.FeedbackThreadCreatedEventHandler.record(
                        thread_model.entity_id)
            else:
                # Thread status changed.
                if thread_model.entity_type == feconf.ENTITY_TYPE_EXPLORATION:
                    (
                        event_services
                        .FeedbackThreadStatusChangedEventHandler
                        .record(
                            thread_model.entity_id, thread_model.status,
                            updated_status)
                    )
        if updated_subject:
            message_model.updated_subject = updated_subject
    feedback_models.GeneralFeedbackMessageModel.update_timestamps_multi(
        message_models)
    feedback_models.GeneralFeedbackMessageModel.put_multi(message_models)

    # Update the message data cache of the threads.
    for thread_model in thread_models:
        thread_model.message_count += 1
        if text:
            thread_model.last_nonempty_message_text = text
            thread_model.last_nonempty_message_author_id = author_id

    # We do a put() even if the status and subject are not updated, so that the
    # last_updated time of the threads reflects the last time a message was
    # added to it.
    old_statuses = [thread_model.status for thread_model in thread_models]
    new_statuses = old_statuses
    if updated_status or updated_subject:
        new_statuses = []
        for index, thread_model in enumerate(thread_models):
            # Can't be the first thread.
            if message_ids[index] != 0:
                if updated_status and (updated_status != thread_model.status):
                    thread_model.status = updated_status
                if updated_subject and (
                        updated_subject != thread_model.subject):
                    thread_model.subject = updated_subject
            new_statuses.append(thread_model.status)
    feedback_models.GeneralFeedbackThreadModel.update_timestamps_multi(
        thread_models)
    feedback_models.GeneralFeedbackThreadModel.put_multi(thread_models)

    # For each thread, we do a put on the suggestion linked (if it exists) to
    # the thread, so that the last_updated time changes to show that there is
    # activity in the thread.
    thread_ids_that_have_linked_suggestions = []
    for thread_model in thread_models:
        if thread_model.has_suggestion:
            thread_ids_that_have_linked_suggestions.append(thread_model.id)
    general_suggestion_models = (
        suggestion_models.GeneralSuggestionModel.get_multi(
            thread_ids_that_have_linked_suggestions)
    )
    suggestion_models_to_update = []
    for suggestion_model in general_suggestion_models:
        # As the thread is created before the suggestion, for the first message
        # we need not update the suggestion.
        if suggestion_model:
            suggestion_models_to_update.append(suggestion_model)
    suggestion_models.GeneralSuggestionModel.update_timestamps_multi(
        suggestion_models_to_update)
    suggestion_models.GeneralSuggestionModel.put_multi(
        suggestion_models_to_update)

    if (feconf.CAN_SEND_EMAILS and (
            feconf.CAN_SEND_FEEDBACK_MESSAGE_EMAILS and
            user_services.is_user_registered(author_id)) and
            # TODO(#12079): Figure out a better way to avoid sending feedback
            # thread emails for contributor dashboard suggestions.
            (len(text) > 0 or old_statuses[index] != new_statuses[index])):
        for index, thread_model in enumerate(thread_models):
            _add_message_to_email_buffer(
                author_id, thread_model.id, message_ids[index],
                len(text), old_statuses[index], new_statuses[index])

    if author_id:
        subscription_services.subscribe_to_threads(author_id, thread_ids)
        add_message_ids_to_read_by_list(author_id, message_identifiers)

    # Convert the GeneralFeedbackMessageModels into a list of FeedbackMessage
    # domain objects.
    feedback_messages = [
        _get_message_from_model(message_model) for message_model in
        message_models
    ]

    return feedback_messages
Example #5
0
def create_message(
        exploration_id, thread_id, author_id, updated_status, updated_subject,
        text, received_via_email=False):
    """Creates a new message for the thread and subscribes the author to the
    thread.

    Args:
        exploration_id: str. The exploration id the thread belongs to.
        thread_id: str. The thread id the message belongs to.
        author_id: str. The author id who creates this message.
        updated_status: str. one of STATUS_CHOICES. New thread status.
            Must be supplied if this is the first message of a thread. For the
            rest of the thread, should exist only when the status changes.
        updated_subject: str. New thread subject. Must be supplied if this is
            the first message of a thread. For the rest of the thread, should
            exist only when the subject changes.
        text: str. The text of the feedback message. This may be ''.
        received_via_email: bool. Whether new message is received via email or
            web.
    """
    from core.domain import event_services
    # Get the thread at the outset, in order to check that the thread_id passed
    # in is valid.
    full_thread_id = (
        feedback_models.FeedbackThreadModel.generate_full_thread_id(
            exploration_id, thread_id))
    thread = feedback_models.FeedbackThreadModel.get(full_thread_id)

    message_id = feedback_models.FeedbackMessageModel.get_message_count(
        exploration_id, thread_id)
    msg = feedback_models.FeedbackMessageModel.create(
        exploration_id, thread_id, message_id)
    msg.thread_id = full_thread_id
    msg.message_id = message_id
    msg.author_id = author_id
    if updated_status:
        if message_id == 0:
            # New thread.
            event_services.FeedbackThreadCreatedEventHandler.record(
                thread.exploration_id)
        else:
            # Thread status changed.
            event_services.FeedbackThreadStatusChangedEventHandler.record(
                thread.exploration_id, thread.status, updated_status)

        msg.updated_status = updated_status
    if updated_subject:
        msg.updated_subject = updated_subject
    msg.text = text
    msg.received_via_email = received_via_email
    msg.put()

    # Update the message count in the thread.
    if thread.message_count is not None:
        thread.message_count += 1
    else:
        thread.message_count = (
            feedback_models.FeedbackMessageModel.get_message_count(
                exploration_id, thread_id))

    # We do a put() even if the status and subject are not updated, so that the
    # last_updated time of the thread reflects the last time a message was
    # added to it.
    old_status = thread.status
    if message_id != 0 and (updated_status or updated_subject):
        if updated_status and updated_status != thread.status:
            thread.status = updated_status
        if updated_subject and updated_subject != thread.subject:
            thread.subject = updated_subject
    new_status = thread.status
    thread.put()

    if (user_services.is_user_registered(author_id) and
            feconf.CAN_SEND_EMAILS and
            feconf.CAN_SEND_FEEDBACK_MESSAGE_EMAILS):
            # send feedback message email if user is registered.
        _add_message_to_email_buffer(
            author_id, exploration_id, thread_id, message_id, len(text),
            old_status, new_status)

    if author_id:
        subscription_services.subscribe_to_thread(author_id, full_thread_id)
        add_message_id_to_read_by_list(
            exploration_id, thread_id, author_id, message_id)
Example #6
0
def create_message(thread_id,
                   author_id,
                   updated_status,
                   updated_subject,
                   text,
                   received_via_email=False):
    """Creates a new message for the thread and subscribes the author to the
    thread.

    Args:
        thread_id: str. The thread id the message belongs to.
        author_id: str. The author id who creates this message.
        updated_status: str. One of STATUS_CHOICES. New thread status.
            Must be supplied if this is the first message of a thread. For the
            rest of the thread, should exist only when the status changes.
        updated_subject: str. New thread subject. Must be supplied if this is
            the first message of a thread. For the rest of the thread, should
            exist only when the subject changes.
        text: str. The text of the feedback message. This may be ''.
        received_via_email: bool. Whether new message is received via email or
            web.
    """
    from core.domain import event_services
    # Get the thread at the outset, in order to check that the thread_id passed
    # in is valid.
    thread = feedback_models.GeneralFeedbackThreadModel.get(thread_id)

    message_id = feedback_models.GeneralFeedbackMessageModel.get_message_count(
        thread_id)
    message = feedback_models.GeneralFeedbackMessageModel.create(
        thread_id, message_id)
    message.thread_id = thread_id
    message.message_id = message_id
    message.author_id = author_id
    message.text = text
    message.received_via_email = received_via_email
    if updated_status:
        message.updated_status = updated_status
        if message_id == 0:
            # New thread.
            if thread.entity_type == feconf.ENTITY_TYPE_EXPLORATION:
                event_services.FeedbackThreadCreatedEventHandler.record(
                    thread.entity_id)
        else:
            # Thread status changed.
            if thread.entity_type == feconf.ENTITY_TYPE_EXPLORATION:
                event_services.FeedbackThreadStatusChangedEventHandler.record(
                    thread.entity_id, thread.status, updated_status)
    if updated_subject:
        message.updated_subject = updated_subject
    message.put()

    # Update the message data cache of the thread.
    if text:
        thread.last_nonempty_message_text = text
        thread.last_nonempty_message_author_id = author_id
    if thread.message_count is not None:
        thread.message_count += 1
    else:
        thread.message_count = (feedback_models.GeneralFeedbackMessageModel.
                                get_message_count(thread_id))

    # We do a put() even if the status and subject are not updated, so that the
    # last_updated time of the thread reflects the last time a message was added
    # to it.
    old_status = thread.status
    if message_id != 0 and (updated_status or updated_subject):
        if updated_status and updated_status != thread.status:
            thread.status = updated_status
        if updated_subject and updated_subject != thread.subject:
            thread.subject = updated_subject
    new_status = thread.status
    thread.put()

    # We do a put on the suggestion linked (if it exists) to the thread, so that
    # the last_updated time changes to show that there is activity in the
    # thread.
    if thread.has_suggestion:
        suggestion_id = thread_id
        suggestion = (
            suggestion_models.GeneralSuggestionModel.get_by_id(suggestion_id))
        # As the thread is created before the suggestion, for the first message
        # we need not update the suggestion.
        if suggestion:
            suggestion.put()

    if (feconf.CAN_SEND_EMAILS and feconf.CAN_SEND_FEEDBACK_MESSAGE_EMAILS
            and user_services.is_user_registered(author_id)):
        _add_message_to_email_buffer(author_id, thread_id, message_id,
                                     len(text), old_status, new_status)

    if author_id:
        subscription_services.subscribe_to_thread(author_id, thread_id)
        add_message_id_to_read_by_list(thread_id, author_id, message_id)
Example #7
0
def create_message(exploration_id, thread_id, author_id, updated_status,
                   updated_subject, text):
    """Creates a new message for the thread and subscribes the author to the
    thread.

    Returns False if the message with the ID already exists.
    """
    from core.domain import event_services
    # Get the thread at the outset, in order to check that the thread_id passed
    # in is valid.
    full_thread_id = (
        feedback_models.FeedbackThreadModel.generate_full_thread_id(
            exploration_id, thread_id))
    thread = feedback_models.FeedbackThreadModel.get(full_thread_id)

    message_id = feedback_models.FeedbackMessageModel.get_message_count(
        exploration_id, thread_id)
    msg = feedback_models.FeedbackMessageModel.create(exploration_id,
                                                      thread_id, message_id)
    msg.thread_id = full_thread_id
    msg.message_id = message_id
    msg.author_id = author_id
    if updated_status:
        if message_id == 0:
            # New thread.
            event_services.FeedbackThreadCreatedEventHandler.record(
                thread.exploration_id)
        else:
            # Thread status changed.
            event_services.FeedbackThreadStatusChangedEventHandler.record(
                thread.exploration_id, thread.status, updated_status)

        msg.updated_status = updated_status
    if updated_subject:
        msg.updated_subject = updated_subject
    msg.text = text
    msg.put()

    # We do a put() even if the status and subject are not updated, so that the
    # last_updated time of the thread reflects the last time a message was
    # added to it.
    old_status = thread.status
    if message_id != 0 and (updated_status or updated_subject):
        if updated_status and updated_status != thread.status:
            thread.status = updated_status
        if updated_subject and updated_subject != thread.subject:
            thread.subject = updated_subject
    new_status = thread.status
    thread.put()

    if (user_services.is_user_registered(author_id) and feconf.CAN_SEND_EMAILS
            and feconf.CAN_SEND_FEEDBACK_MESSAGE_EMAILS):
        # send feedback message email if user is registered.
        _add_message_to_email_buffer(author_id,
                                     exploration_id, thread_id, message_id,
                                     len(text), old_status, new_status)

    if author_id:
        subscription_services.subscribe_to_thread(author_id, full_thread_id)

    return True