def handle_abc_media(msg_id, msg_from, data):
    content = data.get("content", {})
    platform = get_platform(msg_from)
    platform.is_typing = False
    platform.save()
    if not Message.message_exits(platform, msg_id):
        if content.get("type", "").startswith("image/"):
            message_m: Message = Message(
                platform=platform,
                platform_message_id=msg_id,
                image=content.get("uri"),
                direction=Message.FROM_CUSTOMER,
                state=Message.DELIVERED,
            )
            message_m.save()
            operator_interface.tasks.process_message.delay(message_m.id)
            text = content.get("title", "").replace("", "")
            if text:
                message_m: Message = Message(
                    platform=platform,
                    platform_message_id=msg_id,
                    text=html.conditional_escape(text),
                    direction=Message.FROM_CUSTOMER,
                    state=Message.DELIVERED,
                )
                message_m.save()
                operator_interface.tasks.process_message.delay(message_m.id)
    send_abc_notification(msg_id, msg_from, "consumed")
def handle_as207960_file(msg_id, msg_platform, msg_conv_id, metadata, content):
    platform = get_platform(msg_platform, msg_conv_id, metadata)
    platform.is_typing = False
    platform.save()
    if not Message.message_exits(platform, msg_id):
        if content.get("media_type", "").startswith("image/"):
            message_m: Message = Message(
                platform=platform,
                platform_message_id=msg_id,
                image=content.get("url"),
                direction=Message.FROM_CUSTOMER,
                state=Message.DELIVERED,
            )
            message_m.save()
            operator_interface.tasks.process_message.delay(message_m.id)
        else:
            message_m: Message = Message(
                platform=platform,
                platform_message_id=msg_id,
                text=content.get("url"),
                direction=Message.FROM_CUSTOMER,
                state=Message.DELIVERED,
            )
            message_m.save()
            operator_interface.tasks.process_message.delay(message_m.id)
Ejemplo n.º 3
0
def handle_whatsapp(msg_id, msg_from, data):
    text = data.get("Body")
    platform = get_platform(msg_from)
    if not Message.message_exits(platform, msg_id):
        if text:
            message_m: Message = Message(
                platform=platform,
                platform_message_id=msg_id,
                text=html.conditional_escape(text),
                direction=Message.FROM_CUSTOMER,
                state=Message.DELIVERED,
            )
            message_m.save()
            operator_interface.tasks.process_message.delay(message_m.id)
def handle_as207960_text(msg_id, msg_platform, msg_conv_id, metadata, content):
    platform = get_platform(msg_platform, msg_conv_id, metadata)
    platform.is_typing = False
    platform.save()
    if not Message.message_exits(platform, msg_id):
        if content:
            message_m: Message = Message(
                platform=platform,
                platform_message_id=msg_id,
                text=html.conditional_escape(content),
                direction=Message.FROM_CUSTOMER,
                state=Message.DELIVERED,
            )
            message_m.save()
            operator_interface.tasks.process_message.delay(message_m.id)
def handle_facebook_optin(psid: dict, optin: dict) -> None:
    user_id = None
    if optin.get("ref"):
        try:
            ref = jwt.decode(
                optin.get("ref"), settings.FACEBOOK_OPTIN_SECRET, algorithms=["HS256"]
            )
            user_id = ref.get("cust_id")
        except jwt.exceptions.InvalidTokenError:
            return
    psid: str = psid["sender"]
    platform: ConversationPlatform = ConversationPlatform.exists(
        ConversationPlatform.FACEBOOK, psid
    )
    if not platform:
        if not user_id:
            user_id = attempt_get_user_id(psid)
        platform = ConversationPlatform.create(
            ConversationPlatform.FACEBOOK, psid, customer_user_id=user_id
        )

    update_facebook_profile.delay(psid, platform.conversation.id)
    if user_id:
        platform.conversation.update_user_id(user_id)
    message_m: Message = Message(
        platform=platform,
        message_id=uuid.uuid4(),
        text="Thanks for opting to receive messages from us over Facebook Messenger."
        " We'll be sure to keep you updated.",
        direction=Message.TO_CUSTOMER,
    )
    message_m.save()
    operator_interface.tasks.process_message(message_m.id)
def handle_facebook_postback(psid: dict, postback: dict, timestamp: int) -> None:
    psid: str = psid["sender"]
    payload: str = postback.get("payload")
    title: str = postback.get("title")
    if payload is not None:
        platform: ConversationPlatform = ConversationPlatform.exists(
            ConversationPlatform.FACEBOOK, psid
        )
        if not platform:
            user_id = attempt_get_user_id(psid)
            platform = ConversationPlatform.create(
                ConversationPlatform.FACEBOOK, psid, customer_user_id=user_id
            )
        payload: dict = json.loads(payload)
        action: str = payload.get("action")
        if action == "start_action":
            operator_interface.tasks.process_event.delay(platform.id, "WELCOME")
        else:
            operator_interface.tasks.process_event.delay(platform.id, action)

        message_m: Message = Message(
            platform=platform,
            message_id=uuid.uuid4(),
            text=html.conditional_escape(title),
            direction=Message.FROM_CUSTOMER,
            state=Message.DELIVERED,
            timestamp=datetime.datetime.fromtimestamp(timestamp / 1000),
        )
        message_m.save()
        handle_mark_facebook_message_read.delay(psid)
        operator_interface.tasks.send_message_to_interface.delay(message_m.id)
        update_facebook_profile.delay(psid, platform.conversation.id)
def handle_abc_text(msg_id, msg_from, data):
    text = data.get("content")
    platform = get_platform(msg_from)
    platform.is_typing = False
    platform.save()
    if not Message.message_exits(platform, msg_id):
        if text:
            message_m: Message = Message(
                platform=platform,
                platform_message_id=msg_id,
                text=html.conditional_escape(text),
                direction=Message.FROM_CUSTOMER,
                state=Message.DELIVERED,
            )
            message_m.save()
            operator_interface.tasks.process_message.delay(message_m.id)
    send_abc_notification(msg_id, msg_from, "consumed")
def handle_as207960_oauth_code(msg_id, msg_platform, msg_conv_id, metadata,
                               content):
    platform = get_platform(msg_platform, msg_conv_id, metadata)
    token_response = oauth_client.authorization_code(
        code=content,
        redirect_uri="https://messaging.as207960.net/brand_oauth/redirect/")
    token_data = oauth_client.decode_token(
        token_response["id_token"],
        key=oauth_client.certs()["keys"][0],
        algorithms=oauth_client.
        well_known["id_token_signing_alg_values_supported"],
        issuer=oauth_client.well_known["issuer"],
        access_token=token_response["access_token"],
    )
    platform.conversation.update_user_id(token_data["sub"])
    message = Message(
        platform=platform,
        text="Login complete, thanks!",
        direction=Message.TO_CUSTOMER,
    )
    message.save()
    operator_interface.tasks.process_message.delay(message.id)
def handle_as207960_chatstate(msg_id, msg_platform, msg_conv_id, metadata,
                              content):
    platform = get_platform(msg_platform, msg_conv_id, metadata)
    platform.is_typing = False
    platform.save()
    state = content.get("state")
    if state == "composing":
        platform.is_typing = True
        platform.save()
    elif state == "paused":
        platform.is_typing = False
        platform.save()
    elif state == "request_live_agent":
        platform.is_typing = False
        platform.save()
        m = Message(platform=platform,
                    platform_message_id=msg_id,
                    request_live_agent=True,
                    direction=Message.FROM_CUSTOMER,
                    state=Message.DELIVERED)
        m.save()
        operator_interface.tasks.send_message_to_interface.delay(m.id)
def notif_webhook(request):
    try:
        data = json.loads(request.body)
    except json.JSONDecodeError:
        return HttpResponseBadRequest()

    logger.debug(f"Got event from ABC notification webhook: {data}")

    msg_id = data.get("id")
    from_id = data.get("from")
    msg_event = data.get("event")
    conv: ConversationPlatform = ConversationPlatform.objects.filter(
        platform=ConversationPlatform.ABC, platform_id=from_id).first()
    msg: Message = Message.objects.filter(message_id=msg_id).first()

    if msg_event == "failed":
        msg_fail_reason = data.get("reason", {})
        msg_error_code = msg_fail_reason.get("code")
        if msg_error_code == 87 and conv:
            m = Message(
                platform=conv,
                platform_message_id=msg_id,
                end=True,
                direction=Message.FROM_CUSTOMER,
                state=Message.DELIVERED,
            )
            m.save()
            operator_interface.tasks.process_message.delay(m.id)
        if msg:
            msg.state = Message.FAILED
            msg.save()
    elif msg_event == "accepted" and msg and msg.state != Message.READ:
        msg.state = Message.DELIVERED
        msg.save()
    elif msg_event == "consumed" and msg:
        msg.state = Message.READ
        msg.save()

    return HttpResponse("")
Ejemplo n.º 11
0
def account_linking(request):
    state = request.GET.get("state")

    try:
        state = models.AccountLinkingState.objects.get(id=state)
    except models.AccountLinkingState.DoesNotExist:
        return HttpResponseBadRequest()

    if state.timestamp + datetime.timedelta(minutes=5) < timezone.now():
        return HttpResponseBadRequest()
    state.conversation.conversation.update_user_id(request.user.username)
    state.delete()

    message = Message(
        platform=state.conversation,
        text="Login complete, thanks!",
        direction=Message.TO_CUSTOMER,
    )
    message.save()
    operator_interface.tasks.process_message.delay(message.id)

    return HttpResponse(
        '<script type="text/javascript">window.close();</script><h1>You can now close this window</h1>'
    )
Ejemplo n.º 12
0
def handle_azure_message(msg):
    conversation = event_to_conversation(msg)
    mid = msg["id"]
    timestamp = msg["timestamp"]
    text = msg.get("text")

    if not Message.message_exits(conversation, mid):
        message_m = Message(
            conversation=conversation,
            message_id=mid,
            direction=Message.FROM_CUSTOMER,
            state=Message.DELIVERED,
            timestamp=dateutil.parser.parse(timestamp),
        )

        if text:
            message_m.text = text
        else:
            return

        message_m.save()
        operator_interface.tasks.process_message.delay(message_m.id)
def handle_abc_own(data: dict):
    msg_from: str = data.get("from")
    msg_id: str = data.get("id")
    device: str = data.get("device")
    capabilities: [str] = data.get("capabilities")
    msg_locale: str = data.get("locale")
    # msg_group: str = data.get("group")
    # msg_intent: str = data.get("intent")
    contents: dict = data.get("contents")

    platform = get_platform(msg_from)
    conversation = platform.conversation
    if not platform.additional_platform_data:
        info = {}
    else:
        try:
            info = json.loads(platform.additional_platform_data)
        except json.JSONDecodeError:
            info = {}

    info["current_capabilities"] = capabilities

    if conversation.conversation_user_id:
        django_keycloak_auth.users.update_user(
            str(conversation.conversation_user_id),
            locale=msg_locale,
            force_update=False,
        )

    if not Message.message_exits(platform, msg_id):
        if contents.get("text"):
            platform.is_typing = False
            platform.save()
            message_m: Message = Message(platform=platform,
                                         platform_message_id=msg_id,
                                         text=html.conditional_escape(
                                             contents["text"]),
                                         direction=Message.FROM_CUSTOMER,
                                         state=Message.DELIVERED,
                                         device_data=device)
            message_m.save()
            operator_interface.tasks.process_message.delay(message_m.id)
        elif contents.get("action"):
            action: str = contents["action"]
            if action == "typing_start":
                platform.is_typing = True
                platform.save()
            elif action == "typing_end":
                platform.is_typing = False
                platform.save()
            elif action == "close":
                platform.is_typing = False
                platform.save()
                m = Message(platform=platform,
                            platform_message_id=msg_id,
                            end=True,
                            direction=Message.FROM_CUSTOMER,
                            state=Message.DELIVERED,
                            device_data=device)
                m.save()
                operator_interface.tasks.send_message_to_interface.delay(m.id)

    platform.additional_platform_data = json.dumps(info)
    platform.save()

    for attachment in data.get("attachments", []):
        contents: str = attachment.get("contents")
        name: str = attachment.get("name")
        mime_type: str = attachment.get("mime-type")
        if contents:
            try:
                contents: bytes = base64.b64decode(contents)
            except ValueError:
                continue
            fs = DefaultStorage()
            file_name = fs.save(name, BytesIO(contents))

            if mime_type.startswith("image"):
                m = Message(platform=platform,
                            platform_message_id=msg_id,
                            direction=Message.FROM_CUSTOMER,
                            state=Message.DELIVERED,
                            device_data=device,
                            image=fs.base_url + file_name)
            else:
                m = Message(
                    platform=platform,
                    platform_message_id=msg_id,
                    direction=Message.FROM_CUSTOMER,
                    state=Message.DELIVERED,
                    device_data=device,
                    text=
                    f"<a href=\"{fs.base_url + file_name}\" target=\"_blank\">{name}</a>",
                )
            m.save()
            operator_interface.tasks.process_message.delay(m.id)
def handle_facebook_message(psid: dict, message: dict, timestamp: int) -> None:
    text: typing.Text = message.get("text")
    reply_to = message.get("reply_to", {})
    attachments: typing.List[typing.Dict] = message.get("attachments")
    mid: typing.Text = message["mid"]
    is_echo: bool = message.get("is_echo")
    psid: typing.Text = psid["sender"] if not is_echo else psid["recipient"]
    platform: ConversationPlatform = ConversationPlatform.exists(
        ConversationPlatform.FACEBOOK, psid
    )
    if not platform:
        user_id = attempt_get_user_id(psid)
        platform = ConversationPlatform.create(
            ConversationPlatform.FACEBOOK, psid, customer_user_id=user_id
        )
    message_m: typing.Optional[Message] = None
    if not is_echo:
        update_facebook_profile(psid, platform.conversation.id)
        if not Message.message_exits(platform, mid):
            handle_mark_facebook_message_read.delay(psid)
            if text:
                message_m = Message(
                    platform=platform,
                    platform_message_id=mid,
                    text=html.conditional_escape(text),
                    direction=Message.FROM_CUSTOMER,
                    state=Message.DELIVERED,
                    timestamp=datetime.datetime.fromtimestamp(timestamp / 1000),
                )
            if attachments:
                for attachment in attachments:
                    payload = attachment["payload"]
                    att_type: typing.Text = attachment.get("type")
                    if att_type == "image" or att_type == "file":
                        url = payload.get("url")
                        r = requests.get(url)
                        if r.status_code == 200:
                            orig_file_name = os.path.basename(
                                urllib.parse.urlparse(url).path
                            )
                            fs = DefaultStorage()
                            file_name = fs.save(orig_file_name, BytesIO(r.content))

                            if att_type == "image":
                                message_m = Message(
                                    platform=platform,
                                    platform_message_id=mid,
                                    image=fs.base_url + file_name,
                                    direction=Message.FROM_CUSTOMER,
                                    state=Message.DELIVERED,
                                    timestamp=datetime.datetime.fromtimestamp(
                                        timestamp / 1000
                                    ),
                                )
                            else:
                                message_m = Message(
                                    platform=platform,
                                    platform_message_id=mid,
                                    direction=Message.FROM_CUSTOMER,
                                    state=Message.DELIVERED,
                                    timestamp=datetime.datetime.fromtimestamp(
                                        timestamp / 1000
                                    ),
                                    text=f'<a href="{fs.base_url + file_name}" target="_blank">'
                                    f"{html.conditional_escape(orig_file_name)}"
                                    f"</a>",
                                )
                    elif att_type == "location":
                        message_m = Message(
                            platform=platform,
                            platform_message_id=mid,
                            direction=Message.FROM_CUSTOMER,
                            state=Message.DELIVERED,
                            timestamp=datetime.datetime.fromtimestamp(timestamp / 1000),
                            text=f"<a href=\"{attachment.get('url')}\" target=\"_blank\">Location</a>",
                        )
                    elif att_type == "fallback":
                        message_m = Message(
                            platform=platform,
                            platform_message_id=mid,
                            direction=Message.FROM_CUSTOMER,
                            state=Message.DELIVERED,
                            timestamp=datetime.datetime.fromtimestamp(timestamp / 1000),
                            text=f"<a href=\"{payload.get('url')}\" target=\"_blank\">{payload.get('title')}</a>",
                        )
    else:
        if not Message.message_exits(platform, mid):
            message_m: Message = Message(
                platform=platform,
                platform_message_id=mid,
                text=html.conditional_escape(text) if text else "",
                direction=Message.TO_CUSTOMER,
                state=operator_interface.models.Message.DELIVERED,
            )

    if message_m:
        if reply_to:
            reply_to_mid = reply_to.get("mid")
            reply_to_m = Message.objects.filter(platform_message_id=reply_to_mid).first()
            if reply_to_m:
                message_m.reply_to = reply_to_m
        message_m.save()
        operator_interface.tasks.process_message.delay(message_m.id)
def handle_twitter_message(mid: str, psid, message, user):
    text: str = message.get("text")
    attachment: dict = message.get("attachment")
    if text is not None:
        platform: ConversationPlatform = ConversationPlatform.exists(
            ConversationPlatform.TWITTER, psid)
        if not platform:
            kc_user = django_keycloak_auth.users.get_or_create_user(
                federated_provider="twitter",
                federated_user_id=user.get("id"),
                federated_user_name=user.get("screen_name"),
                first_name=user.get("name"),
            )
            if kc_user:
                django_keycloak_auth.users.link_roles_to_user(
                    kc_user.get("id"), ["customer"])
                user_id = kc_user.get("id")
            platform = ConversationPlatform.create(
                ConversationPlatform.TWITTER, psid, customer_user_id=user_id)
        conversation = platform.conversation

        if not conversation.conversation_user_id:
            kc_user = django_keycloak_auth.users.get_or_create_user(
                federated_provider="twitter",
                federated_user_id=user.get("id"),
                federated_user_name=user.get("screen_name"),
                first_name=user.get("name"),
            )
            if kc_user:
                django_keycloak_auth.users.link_roles_to_user(
                    kc_user.get("id"), ["customer"])
                conversation.update_user_id(kc_user.get("id"))

        if conversation.conversation_user_id:
            django_keycloak_auth.users.link_federated_identity_if_not_exists(
                str(conversation.conversation_user_id),
                federated_provider="twitter",
                federated_user_id=user.get("id"),
                federated_user_name=user.get("screen_name"),
            )

            django_keycloak_auth.users.update_user(str(
                conversation.conversation_user_id),
                                                   first_name=user.get("name"))

        if not Message.message_exits(platform, mid):
            message_m: Message = Message(
                platform=platform,
                platform_message_id=mid,
                text=html.conditional_escape(text.strip()),
                direction=Message.FROM_CUSTOMER,
                state=Message.DELIVERED,
            )
            platform.is_typing = False
            platform.save()

            if attachment:
                if attachment["type"] == "media":
                    creds = views.get_creds()
                    url: str = attachment["media"]["media_url_https"]
                    indices: typing.Tuple = attachment["media"]["indices"]
                    message_m.text = (text[:indices[0]] +
                                      text[indices[1]:]).strip()

                    media_r = requests.get(url, auth=creds)
                    if media_r.status_code == 200:
                        orig_file_name = os.path.basename(
                            urllib.parse.urlparse(url).path)
                        fs = DefaultStorage()
                        file_name = fs.save(orig_file_name,
                                            BytesIO(media_r.content))
                        message_m.image = fs.base_url + file_name

            message_m.save()
            handle_mark_twitter_message_read.delay(psid, mid)
            operator_interface.tasks.process_message.delay(message_m.id)

        file_name = os.path.basename(
            urllib.parse.urlparse(user["profile_image_url_https"]).path)
        r = requests.get(user["profile_image_url_https"])
        if r.status_code == 200:
            if not conversation.conversation_pic:
                conversation.conversation_pic.save(
                    file_name,
                    InMemoryUploadedFile(
                        file=BytesIO(r.content),
                        size=len(r.content),
                        charset=r.encoding,
                        content_type=r.headers.get("content-type"),
                        field_name=file_name,
                        name=file_name,
                    ),
                )
            django_keycloak_auth.users.update_user(
                str(conversation.conversation_user_id),
                profile_picture=conversation.conversation_pic.url,
            )
            conversation.save()
Ejemplo n.º 16
0
def handle_telegram_message(message):
    text = message.get("text")
    contact = message.get("contact")
    photo = message.get("photo")
    sticker = message.get("sticker")
    document = message.get("document")
    entities = message.get("entities")
    caption = message.get("caption")
    mid = message["message_id"]
    chat_id = message["chat"]["id"]
    timestamp = message["date"]
    conversation = Conversation.get_or_create_conversation(
        Conversation.TELEGRAM, chat_id, agent_responding=False)
    update_telegram_profile(chat_id, conversation.id)
    if not Message.message_exits(conversation, mid):
        message_m = Message(
            conversation=conversation,
            message_id=mid,
            direction=Message.FROM_CUSTOMER,
            state=Message.DELIVERED,
            timestamp=datetime.datetime.fromtimestamp(timestamp),
        )
        if text:
            if entities:
                for entity in entities:
                    if entity["type"] == "bot_command":
                        command = text[entity["offset"] + 1:entity["offset"] +
                                       entity["length"]]
                        if command == "start":
                            operator_interface.tasks.process_event.delay(
                                conversation.id, "WELCOME")
                        else:
                            operator_interface.tasks.process_event.delay(
                                conversation.id, command)
                    else:
                        message_m.text = text
            else:
                message_m.text = text
        elif photo or sticker:
            if photo:
                photo = photo[-1]
            else:
                photo = sticker
            file = requests.get(
                f"https://api.telegram.org/bot{settings.TELEGRAM_TOKEN}/getFile",
                json={"file_id": photo["file_id"]},
            )
            file.raise_for_status()
            fs = DefaultStorage()
            file_name = fs.save(photo["file_id"], BytesIO(file.content))

            message_m.image = fs.base_url + file_name
            if caption:
                message.text = caption
        elif document:
            file_name = document["file_name"] if document.get(
                "file_name") else "File"
            file = requests.get(
                f"https://api.telegram.org/bot{settings.TELEGRAM_TOKEN}/getFile",
                json={"file_id": document["file_id"]},
            )
            file.raise_for_status()
            fs = DefaultStorage()
            file_url = fs.save(photo["file_id"], BytesIO(file.content))
            message_m.text = (
                f'<a href="{fs.base_url + file_url}" target="_blank">{file_name}</a>'
            )
            if caption:
                message.text = caption
        elif contact:
            message_m.text = contact["phone_number"]
        else:
            return
        message_m.save()
        operator_interface.tasks.process_message.delay(message_m.id)
def send_message(request, customer_id):
    if request.method != "POST":
        return HttpResponseNotAllowed(permitted_methods=["POST"])

    auth = request.META.get("HTTP_AUTHORIZATION")
    if not auth or not auth.startswith("Bearer "):
        return HttpResponseForbidden()

    try:
        claims = django_keycloak_auth.clients.verify_token(
            auth[len("Bearer "):].strip()
        )
    except keycloak.exceptions.KeycloakClientError:
        return HttpResponseForbidden()

    if "send-messages" not in claims.get("resource_access", {}).get(
            "bot-server", {}
    ).get("roles", []):
        return HttpResponseForbidden()

    try:
        customer = django_keycloak_auth.users.get_user_by_id(customer_id).user
    except keycloak.exceptions.KeycloakClientError:
        raise Http404()

    try:
        data = json.loads(request.body)
    except json.JSONDecodeError:
        return HttpResponseBadRequest()

    text = data.get("text")
    tag = data.get("tag")

    if not text:
        return HttpResponseBadRequest()

    platform = None
    conv = None
    try:
        conv = Conversation.objects.get(conversation_user_id=customer_id)
        platform = conv.last_usable_platform(tag, True, text)
    except Conversation.DoesNotExist:
        pass

    if platform is None:
        mobile_numbers = []
        other_numbers = []
        for n in customer.get("attributes", {}).get("phone", []):
            try:
                n = phonenumbers.parse(n, settings.PHONENUMBER_DEFAULT_REGION)
            except phonenumbers.phonenumberutil.NumberParseException:
                continue
            if phonenumbers.is_valid_number(n):
                if (
                        phonenumbers.phonenumberutil.number_type(n)
                        == phonenumbers.PhoneNumberType.MOBILE
                ):
                    mobile_numbers.append(n)
                else:
                    other_numbers.append(n)
        if len(mobile_numbers) or len(other_numbers):
            for n in mobile_numbers:
                formatted_num = phonenumbers.format_number(
                    n, phonenumbers.PhoneNumberFormat.E164
                )
                try:
                    platform = ConversationPlatform.objects.get(
                        platform=ConversationPlatform.WHATSAPP,
                        platform_id=formatted_num,
                    )
                    if not platform.can_message(tag, True, text):
                        platform = None
                    else:
                        break
                except ConversationPlatform.DoesNotExist:
                    pass
                try:
                    platform = ConversationPlatform.objects.get(
                        platform=ConversationPlatform.AS207960,
                        platform_id=f"msisdn-messaging;{formatted_num}",
                    )
                    break
                except ConversationPlatform.DoesNotExist:
                    pass
                try:
                    platform = ConversationPlatform.objects.get(
                        platform=ConversationPlatform.SMS,
                        platform_id=formatted_num,
                    )
                    break
                except ConversationPlatform.DoesNotExist:
                    pass

            if not platform:
                for n in other_numbers:
                    formatted_num = phonenumbers.format_number(
                        n, phonenumbers.PhoneNumberFormat.E164
                    )
                    try:
                        platform = ConversationPlatform.objects.get(
                            platform=ConversationPlatform.WHATSAPP,
                            platform_id=formatted_num,
                        )
                        if not platform.can_message(tag, True, text):
                            platform = None
                        else:
                            break
                    except ConversationPlatform.DoesNotExist:
                        pass
                    try:
                        platform = ConversationPlatform.objects.get(
                            platform=ConversationPlatform.AS207960,
                            platform_id=f"msisdn-messaging;{formatted_num}",
                        )
                        break
                    except ConversationPlatform.DoesNotExist:
                        pass
                    try:
                        platform = ConversationPlatform.objects.get(
                            platform=ConversationPlatform.SMS,
                            platform_id=formatted_num
                        )
                        break
                    except ConversationPlatform.DoesNotExist:
                        pass

            if not platform:
                if not conv:
                    conv = Conversation(conversation_user_id=customer_id)
                    conv.save()

                formatted_num = phonenumbers.format_number(
                    mobile_numbers[0], phonenumbers.PhoneNumberFormat.E164
                ) if len(mobile_numbers) else phonenumbers.format_number(
                other_numbers[0], phonenumbers.PhoneNumberFormat.E164
                )

                if operator_interface.models.ConversationPlatform.is_whatsapp_template(text):
                    platform_id = operator_interface.models.ConversationPlatform.WHATSAPP
                    platform_rcpt_id = formatted_num
                else:
                    platform_id = operator_interface.models.ConversationPlatform.AS207960
                    platform_rcpt_id = f"msisdn-messaging;{formatted_num}"

                platform = ConversationPlatform(
                    conversation=conv,
                    platform=platform_id,
                    platform_id=platform_rcpt_id,
                    additional_platform_data=json.dumps({
                        "try_others": [phonenumbers.format_number(
                            n, phonenumbers.PhoneNumberFormat.E164
                        ) for n in mobile_numbers] + [phonenumbers.format_number(
                            n, phonenumbers.PhoneNumberFormat.E164
                        ) for n in other_numbers]
                    })
                )
                platform.save()
            else:
                platform.conversation.update_user_id(customer_id)
        else:
            return HttpResponse(
                json.dumps({"status": "no_platform_available"}),
                content_type="application/json",
            )

    message = Message(
        platform=platform,
        text=text,
        direction=Message.TO_CUSTOMER,
        message_id=uuid.uuid4(),
    )
    message.save()
    operator_interface.tasks.process_message.delay(message.id)

    return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")
def handle_text(platform: ConversationPlatform, text: str):
    operator_interface.tasks.process_typing_on.delay(platform.id)

    r = requests.post(
        f"{settings.RASA_HTTP_URL}/webhooks/rest/webhook?stream=true",
        json={"sender": f"CONV:{platform.id}", "message": text},
        stream=True,
    )
    r.raise_for_status()

    items = r.iter_lines(None, True)
    out_data = []
    for item in items:
        if item:
            try:
                data = json.loads(item)
            except json.JSONDecodeError:
                continue

            logger.debug(f"Got messages from rasa callback: {data}")

            if not data.get("recipient_id"):
                continue

            message = Message(
                platform=platform,
                direction=Message.TO_CUSTOMER,
                message_id=uuid.uuid4(),
            )

            if data.get("text"):
                message.text = data["text"]
            elif data.get("image"):
                message.image = data["image"]
            elif data.get("custom"):
                custom = data["custom"]
                if not custom.get("type"):
                    continue
                event_type = custom["type"]

                if event_type == "payment":
                    # TODO: Integrate with new system
                    # payment_id = custom.get("payment_id")
                    # payment_o = payment.models.Payment.objects.get(id=payment_id)

                    message.text = "To complete payment follow this link 💸"
                    # message.payment_request = payment_o
                    message.save()
                elif event_type == "request_human":
                    platform.conversation.agent_responding = False
                    platform.conversation.save()

                    operator_interface.tasks.send_message_notifications.delay(
                        {
                            "type": "alert",
                            "cid": platform.conversation.id,
                            "name": platform.conversation.conversation_name,
                            "text": "Human needed!",
                        }
                    )
                    continue
                elif event_type == "request":
                    message.text = custom.get("text", "")
                    message.request = custom.get("request")
                elif event_type == "card":
                    message.card = json.dumps(custom.get("card"))
                elif event_type == "selection":
                    message.selection = json.dumps(custom.get("selection"))
                elif event_type == "restart":
                    message.end = True
                else:
                    continue
            else:
                continue
            message.save()

            if data.get("buttons"):
                for button in data["buttons"]:
                    suggestion = MessageSuggestion(
                        message=message, suggested_response=button["payload"]
                    )
                    suggestion.save()

            out_data.append(operator_interface.tasks.process_message(message.id))

    return out_data