from flask import jsonify, redirect, render_template, session, url_for from flask_login import current_user from notifications_python_client.errors import HTTPError from app import current_service, notification_api_client, service_api_client from app.main import main from app.main.forms import SearchByNameForm from app.models.template_list import TemplateList from app.utils.user import user_has_permissions from notifications_utils.recipients import format_phone_number_human_readable from notifications_utils.template import SMSPreviewTemplate @main.route("/services//conversation/") @user_has_permissions("view_activity") def conversation(service_id, notification_id): user_number = get_user_number(service_id, notification_id) return render_template( "views/conversations/conversation.html", user_number=user_number, partials=get_conversation_partials(service_id, user_number), updates_url=url_for( ".conversation_updates", service_id=service_id, notification_id=notification_id, ), notification_id=notification_id, ) @main.route("/services//conversation/.json") @user_has_permissions("view_activity") def conversation_updates(service_id, notification_id): return jsonify( get_conversation_partials( service_id, get_user_number(service_id, notification_id) ) ) @main.route( "/services//conversation//reply-with" ) @main.route( "/services//conversation//reply-with/from-folder/" ) @user_has_permissions("send_messages") def conversation_reply( service_id, notification_id, from_folder=None, ): return render_template( "views/templates/choose-reply.html", templates_and_folders=TemplateList( current_service, template_folder_id=from_folder, user=current_user, template_type="sms", ), template_folder_path=current_service.get_template_folder_path(from_folder), search_form=SearchByNameForm(), notification_id=notification_id, template_type="sms", ) @main.route( "/services//conversation//reply-with/" ) @user_has_permissions("send_messages") def conversation_reply_with_template( service_id, notification_id, template_id, ): session["recipient"] = get_user_number(service_id, notification_id) session["placeholders"] = {"phone number": session["recipient"]} return redirect( url_for( "main.send_one_off_step", service_id=service_id, template_id=template_id, step_index=1, ) ) def get_conversation_partials(service_id, user_number): return { "messages": render_template( "views/conversations/messages.html", conversation=get_sms_thread(service_id, user_number), ) } def get_user_number(service_id, notification_id): try: user_number = service_api_client.get_inbound_sms_by_id( service_id, notification_id )["user_number"] except HTTPError as e: if e.status_code != 404: raise user_number = notification_api_client.get_notification( service_id, notification_id )["to"] return format_phone_number_human_readable(user_number) def get_sms_thread(service_id, user_number): for notification in sorted( ( # noqa: B020 notification_api_client.get_notifications_for_service( service_id, to=user_number, template_type="sms" )["notifications"] + service_api_client.get_inbound_sms(service_id, user_number=user_number)[ "data" ] ), key=lambda notification: notification["created_at"], ): is_inbound = "notify_number" in notification redact_personalisation = ( not is_inbound and notification["template"]["redact_personalisation"] ) if redact_personalisation: notification["personalisation"] = {} yield { "inbound": is_inbound, "content": SMSPreviewTemplate( { "template_type": "sms", "content": ( notification["content"] if is_inbound else notification["template"]["content"] ), }, notification.get("personalisation"), downgrade_non_sms_characters=(not is_inbound), redact_missing_personalisation=redact_personalisation, ), "created_at": notification["created_at"], "status": notification.get("status"), "id": notification["id"], }