diff --git a/bots/tasks.py b/bots/tasks.py
index 26fb71ff9..7b0ae76b8 100644
--- a/bots/tasks.py
+++ b/bots/tasks.py
@@ -154,6 +154,7 @@ def send_broadcast_msgs_chunked(
buttons: list[ReplyButton] = None,
convo_qs: QuerySet[Conversation],
bi: BotIntegration,
+ medium: str = "Voice Call",
):
convo_ids = list(convo_qs.values_list("id", flat=True))
for i in range(0, len(convo_ids), 100):
@@ -165,6 +166,7 @@ def send_broadcast_msgs_chunked(
documents=documents,
bi_id=bi.id,
convo_ids=convo_ids[i : i + 100],
+ medium=medium,
)
diff --git a/daras_ai_v2/bot_integration_widgets.py b/daras_ai_v2/bot_integration_widgets.py
index b6324ce5f..226bb35a2 100644
--- a/daras_ai_v2/bot_integration_widgets.py
+++ b/daras_ai_v2/bot_integration_widgets.py
@@ -5,6 +5,7 @@
from django.db import transaction
from django.utils.text import slugify
from furl import furl
+import langcodes
import gooey_ui as st
from app_users.models import AppUser
@@ -17,6 +18,9 @@
from recipes.CompareLLM import CompareLLMPage
from routers.root import RecipeTabs, chat_route, chat_lib_route
+TWILIO_SUPPORTED_VOICES = ["Google.af-ZA-Standard-A", "Polly.Zeina", "Google.ar-XA-Standard-A", "Google.ar-XA-Standard-B", "Google.ar-XA-Standard-C", "Google.ar-XA-Standard-D", "Google.ar-XA-Wavenet-A", "Google.ar-XA-Wavenet-B", "Google.ar-XA-Wavenet-C", "Google.ar-XA-Wavenet-D", "Polly.Hala-Neural", "Polly.Zayd-Neural", "Google.eu-ES-Standard-A", "Google.bn-IN-Standard-C", "Google.bn-IN-Standard-D", "Google.bn-IN-Wavenet-C", "Google.bn-IN-Wavenet-D", "Google.bg-BG-Standard-A", "Polly.Arlet-Neural", "Google.ca-ES-Standard-A", "Polly.Hiujin-Neural", "Google.yue-HK-Standard-A", "Google.yue-HK-Standard-B", "Google.yue-HK-Standard-C", "Google.yue-HK-Standard-D", "Polly.Zhiyu", "Polly.Zhiyu-Neural", "Google.cmn-CN-Standard-A", "Google.cmn-CN-Standard-B", "Google.cmn-CN-Standard-C", "Google.cmn-CN-Standard-D", "Google.cmn-CN-Wavenet-A", "Google.cmn-CN-Wavenet-B", "Google.cmn-CN-Wavenet-C", "Google.cmn-CN-Wavenet-D", "Google.cmn-TW-Standard-A", "Google.cmn-TW-Standard-B", "Google.cmn-TW-Standard-C", "Google.cmn-TW-Wavenet-A", "Google.cmn-TW-Wavenet-B", "Google.cmn-TW-Wavenet-C", "Google.cs-CZ-Standard-A", "Google.cs-CZ-Wavenet-A", "Polly.Mads", "Polly.Naja", "Polly.Sofie-Neural", "Google.da-DK-Standard-A", "Google.da-DK-Standard-C", "Google.da-DK-Standard-D", "Google.da-DK-Standard-E", "Google.da-DK-Wavenet-A", "Google.da-DK-Wavenet-C", "Google.da-DK-Wavenet-D", "Google.da-DK-Wavenet-E", "Polly.Lisa-Neural", "Google.nl-BE-Standard-A", "Google.nl-BE-Standard-B", "Google.nl-BE-Wavenet-A", "Google.nl-BE-Wavenet-B", "Polly.Lotte", "Polly.Ruben", "Polly.Laura-Neural", "Google.nl-NL-Standard-A", "Google.nl-NL-Standard-B", "Google.nl-NL-Standard-C", "Google.nl-NL-Standard-D", "Google.nl-NL-Standard-E", "Google.nl-NL-Wavenet-A", "Google.nl-NL-Wavenet-B", "Google.nl-NL-Wavenet-C", "Google.nl-NL-Wavenet-D", "Google.nl-NL-Wavenet-E", "Polly.Nicole", "Polly.Russell", "Polly.Olivia-Neural", "Google.en-AU-Standard-A", "Google.en-AU-Standard-B", "Google.en-AU-Standard-C", "Google.en-AU-Standard-D", "Google.en-AU-Wavenet-A", "Google.en-AU-Wavenet-B", "Google.en-AU-Wavenet-C", "Google.en-AU-Wavenet-D", "Google.en-AU-Neural2-A", "Google.en-AU-Neural2-B", "Google.en-AU-Neural2-C", "Google.en-AU-Neural2-D", "Polly.Raveena", "Google.en-IN-Standard-A", "Google.en-IN-Standard-B", "Google.en-IN-Standard-C", "Google.en-IN-Standard-D", "Google.en-IN-Wavenet-A", "Google.en-IN-Wavenet-B", "Google.en-IN-Wavenet-C", "Google.en-IN-Wavenet-D", "Google.en-IN-Neural2-A", "Google.en-IN-Neural2-B", "Google.en-IN-Neural2-C", "Google.en-IN-Neural2-D", "Polly.Niamh-Neural", "Polly.Aria-Neural", "Polly.Ayanda-Neural", "Polly.Amy", "Polly.Brian", "Polly.Emma", "Polly.Amy-Neural", "Polly.Emma-Neural", "Polly.Brian-Neural", "Polly.Arthur-Neural", "Google.en-GB-Standard-A", "Google.en-GB-Standard-B", "Google.en-GB-Standard-C", "Google.en-GB-Standard-D", "Google.en-GB-Standard-F", "Google.en-GB-Wavenet-A", "Google.en-GB-Wavenet-B", "Google.en-GB-Wavenet-C", "Google.en-GB-Wavenet-D", "Google.en-GB-Wavenet-F", "Google.en-GB-Neural2-A", "Google.en-GB-Neural2-B", "Google.en-GB-Neural2-C", "Google.en-GB-Neural2-D", "Google.en-GB-Neural2-F", "Polly.Ivy", "Polly.Joanna", "Polly.Joey", "Polly.Justin", "Polly.Kendra", "Polly.Kimberly", "Polly.Matthew", "Polly.Salli", "child) Polly.Ivy-Neural", "Polly.Joanna-Neural*", "Polly.Kendra-Neural", "child) Polly.Kevin-Neural", "Polly.Kimberly-Neural", "Polly.Salli-Neural", "Polly.Joey-Neural", "child) Polly.Justin-Neural", "Polly.Matthew-Neural*", "Polly.Ruth-Neural", "Polly.Stephen-Neural", "Polly.Gregory-Neural", "Polly.Danielle-Neural", "Google.en-US-Standard-A", "Google.en-US-Standard-B", "Google.en-US-Standard-C", "Google.en-US-Standard-D", "Google.en-US-Standard-E", "Google.en-US-Standard-F", "Google.en-US-Standard-G", "Google.en-US-Standard-H", "Google.en-US-Standard-I", "Google.en-US-Standard-J", "Google.en-US-Wavenet-A", "Google.en-US-Wavenet-B", "Google.en-US-Wavenet-C", "Google.en-US-Wavenet-D", "Google.en-US-Wavenet-E", "Google.en-US-Wavenet-F", "Google.en-US-Wavenet-G", "Google.en-US-Wavenet-H", "Google.en-US-Wavenet-I", "Google.en-US-Wavenet-J", "Google.en-US-Neural2-A", "Google.en-US-Neural2-C", "Google.en-US-Neural2-D", "Google.en-US-Neural2-E", "Google.en-US-Neural2-F", "Google.en-US-Neural2-G", "Google.en-US-Neural2-H", "Google.en-US-Neural2-I", "Google.en-US-Neural2-J", "Polly.Geraint", "Google.fil-PH-Standard-A", "Google.fil-PH-Standard-B", "Google.fil-PH-Standard-C", "Google.fil-PH-Standard-D", "Google.fil-PH-Wavenet-A", "Google.fil-PH-Wavenet-B", "Google.fil-PH-Wavenet-C", "Google.fil-PH-Wavenet-D", "Polly.Suvi-Neural", "Google.fi-FI-Standard-A", "Google.fi-FI-Wavenet-A", "Polly.Isabelle-Neural", "Polly.Chantal", "Polly.Gabrielle-Neural", "Polly.Liam-Neural", "Google.fr-CA-Standard-A", "Google.fr-CA-Standard-B", "Google.fr-CA-Standard-C", "Google.fr-CA-Standard-D", "Google.fr-CA-Wavenet-A", "Google.fr-CA-Wavenet-B", "Google.fr-CA-Wavenet-C", "Google.fr-CA-Wavenet-D", "Google.fr-CA-Neural2-A", "Google.fr-CA-Neural2-B", "Google.fr-CA-Neural2-C", "Google.fr-CA-Neural2-D", "Polly.Céline/Polly.Celine", "Polly.Léa/Polly.Lea", "Polly.Mathieu", "Polly.Lea-Neural", "Polly.Remi-Neural", "Google.fr-FR-Standard-A", "Google.fr-FR-Standard-B", "Google.fr-FR-Standard-C", "Google.fr-FR-Standard-D", "Google.fr-FR-Standard-E", "Google.fr-FR-Wavenet-A", "Google.fr-FR-Wavenet-B", "Google.fr-FR-Wavenet-C", "Google.fr-FR-Wavenet-D", "Google.fr-FR-Wavenet-E", "Google.fr-FR-Neural2-A", "Google.fr-FR-Neural2-B", "Google.fr-FR-Neural2-C", "Google.fr-FR-Neural2-D", "Google.fr-FR-Neural2-E", "Google.gl-ES-Standard-A", "Polly.Hannah-Neural", "Polly.Hans", "Polly.Marlene", "Polly.Vicki", "Polly.Vicki-Neural", "Polly.Daniel-Neural", "Google.de-DE-Standard-A", "Google.de-DE-Standard-B", "Google.de-DE-Standard-C", "Google.de-DE-Standard-D", "Google.de-DE-Standard-E", "Google.de-DE-Standard-F", "Google.de-DE-Wavenet-A", "Google.de-DE-Wavenet-B", "Google.de-DE-Wavenet-C", "Google.de-DE-Wavenet-D", "Google.de-DE-Wavenet-E", "Google.de-DE-Wavenet-F", "Google.de-DE-Neural2-A", "Google.de-DE-Neural2-B", "Google.de-DE-Neural2-C", "Google.de-DE-Neural2-D", "Google.de-DE-Neural2-F", "Google.el-GR-Standard-A", "Google.el-GR-Wavenet-A", "Google.gu-IN-Standard-C", "Google.gu-IN-Standard-D", "Google.gu-IN-Wavenet-C", "Google.gu-IN-Wavenet-D", "Google.he-IL-Standard-A", "Google.he-IL-Standard-B", "Google.he-IL-Standard-C", "Google.he-IL-Standard-D", "Google.he-IL-Wavenet-A", "Google.he-IL-Wavenet-B", "Google.he-IL-Wavenet-C", "Google.he-IL-Wavenet-D", "Polly.Aditi", "Polly.Kajal-Neural", "Google.hi-IN-Standard-A", "Google.hi-IN-Standard-B", "Google.hi-IN-Standard-C", "Google.hi-IN-Standard-D", "Google.hi-IN-Wavenet-A", "Google.hi-IN-Wavenet-B", "Google.hi-IN-Wavenet-C", "Google.hi-IN-Wavenet-D", "Google.hi-IN-Neural2-A", "Google.hi-IN-Neural2-B", "Google.hi-IN-Neural2-C", "Google.hi-IN-Neural2-D", "Google.hu-HU-Standard-A", "Google.hu-HU-Wavenet-A", "Polly.Dóra/Polly.Dora", "Polly.Karl", "Google.is-IS-Standard-A", "Google.id-ID-Standard-A", "Google.id-ID-Standard-B", "Google.id-ID-Standard-C", "Google.id-ID-Standard-D", "Google.id-ID-Wavenet-A", "Google.id-ID-Wavenet-B", "Google.id-ID-Wavenet-C", "Google.id-ID-Wavenet-D", "Polly.Bianca", "Polly.Carla", "Polly.Giorgio", "Polly.Bianca-Neural", "Polly.Adriano-Neural", "Google.it-IT-Standard-B", "Google.it-IT-Standard-C", "Google.it-IT-Standard-D", "Google.it-IT-Wavenet-B", "Google.it-IT-Wavenet-C", "Google.it-IT-Wavenet-D", "Google.it-IT-Neural2-A", "Google.it-IT-Neural2-C", "Polly.Mizuki", "Polly.Takumi", "Polly.Takumi-Neural", "Polly.Kazuha-Neural", "Polly.Tomoko-Neural", "Google.ja-JP-Standard-B", "Google.ja-JP-Standard-C", "Google.ja-JP-Standard-D", "Google.ja-JP-Wavenet-B", "Google.ja-JP-Wavenet-C", "Google.ja-JP-Wavenet-D", "Google.kn-IN-Standard-C", "Google.kn-IN-Standard-D", "Google.kn-IN-Wavenet-C", "Google.kn-IN-Wavenet-D", "Polly.Seoyeon", "Polly.Seoyeon-Neural", "Google.ko-KR-Standard-A", "Google.ko-KR-Standard-B", "Google.ko-KR-Standard-C", "Google.ko-KR-Standard-D", "Google.ko-KR-Wavenet-A", "Google.ko-KR-Wavenet-B", "Google.ko-KR-Wavenet-C", "Google.ko-KR-Wavenet-D", "Google.ko-KR-Neural2-A", "Google.ko-KR-Neural2-B", "Google.ko-KR-Neural2-C", "Google.lv-LV-Standard-A", "Google.lt-LT-Standard-A", "Google.ms-MY-Standard-A", "Google.ms-MY-Standard-B", "Google.ms-MY-Standard-C", "Google.ms-MY-Standard-D", "Google.ms-MY-Wavenet-A", "Google.ms-MY-Wavenet-B", "Google.ms-MY-Wavenet-C", "Google.ms-MY-Wavenet-D", "Google.ml-IN-Wavenet-C", "Google.ml-IN-Wavenet-D", "Google.mr-IN-Standard-A", "Google.mr-IN-Standard-B", "Google.mr-IN-Standard-C", "Google.mr-IN-Wavenet-A", "Google.mr-IN-Wavenet-B", "Google.mr-IN-Wavenet-C", "Polly.Liv", "Polly.Ida-Neural", "Google.nb-NO-Standard-A", "Google.nb-NO-Standard-B", "Google.nb-NO-Standard-C", "Google.nb-NO-Standard-D", "Google.nb-NO-Standard-E", "Google.nb-NO-Wavenet-A", "Google.nb-NO-Wavenet-B", "Google.nb-NO-Wavenet-C", "Google.nb-NO-Wavenet-D", "Google.nb-NO-Wavenet-E", "Polly.Jacek", "Polly.Jan", "Polly.Ewa", "Polly.Maja", "Polly.Ola-Neural", "Google.pl-PL-Standard-A", "Google.pl-PL-Standard-B", "Google.pl-PL-Standard-C", "Google.pl-PL-Standard-D", "Google.pl-PL-Standard-E", "Google.pl-PL-Wavenet-A", "Google.pl-PL-Wavenet-B", "Google.pl-PL-Wavenet-C", "Google.pl-PL-Wavenet-D", "Google.pl-PL-Wavenet-E", "Polly.Camila", "Polly.Ricardo", "Polly.Vitória/Polly.Vitoria", "Polly.Camila-Neural", "Polly.Vitoria-Neural", "Polly.Thiago-Neural", "Google.pt-BR-Standard-B", "Google.pt-BR-Standard-C", "Google.pt-BR-Wavenet-B", "Google.pt-BR-Wavenet-C", "Google.pt-BR-Neural2-A", "Google.pt-BR-Neural2-B", "Google.pt-BR-Neural2-C", "Polly.Cristiano", "Polly.Inês/Polly.Ines", "Polly.Ines-Neural", "Google.pt-PT-Standard-A", "Google.pt-PT-Standard-B", "Google.pt-PT-Standard-C", "Google.pt-PT-Standard-D", "Google.pt-PT-Wavenet-A", "Google.pt-PT-Wavenet-B", "Google.pt-PT-Wavenet-C", "Google.pt-PT-Wavenet-D", "Google.pa-IN-Standard-A", "Google.pa-IN-Standard-B", "Google.pa-IN-Standard-C", "Google.pa-IN-Standard-D", "Google.pa-IN-Wavenet-A", "Google.pa-IN-Wavenet-B", "Google.pa-IN-Wavenet-C", "Google.pa-IN-Wavenet-D", "Polly.Carmen", "Google.ro-RO-Standard-A", "Google.ro-RO-Wavenet-A", "Polly.Maxim", "Polly.Tatyana", "Google.ru-RU-Standard-A", "Google.ru-RU-Standard-B", "Google.ru-RU-Standard-C", "Google.ru-RU-Standard-D", "Google.ru-RU-Standard-E", "Google.ru-RU-Wavenet-A", "Google.ru-RU-Wavenet-B", "Google.ru-RU-Wavenet-C", "Google.ru-RU-Wavenet-D", "Google.ru-RU-Wavenet-E", "Google.sr-RS-Standard-A", "Google.sk-SK-Standard-A", "Google.sk-SK-Wavenet-A", "Polly.Mia", "Polly.Mia-Neural", "Polly.Andres-Neural", "Polly.Conchita", "Polly.Enrique", "Polly.Lucia", "Polly.Lucia-Neural", "Polly.Sergio-Neural", "Google.es-ES-Standard-B", "Google.es-ES-Standard-C", "Google.es-ES-Standard-D", "Google.es-ES-Wavenet-B", "Google.es-ES-Wavenet-C", "Google.es-ES-Wavenet-D", "Google.es-ES-Neural2-A", "Google.es-ES-Neural2-B", "Google.es-ES-Neural2-C", "Google.es-ES-Neural2-D", "Google.es-ES-Neural2-E", "Google.es-ES-Neural2-F", "man", "woman", "Polly.Lupe", "Polly.Miguel", "Polly.Penélope/Polly.Penelope", "Polly.Lupe-Neural", "Polly.Pedro-Neural", "Google.es-US-Standard-A", "Google.es-US-Standard-B", "Google.es-US-Standard-C", "Google.es-US-Wavenet-A", "Google.es-US-Wavenet-B", "Google.es-US-Wavenet-C", "Google.es-US-Neural2-A", "Google.es-US-Neural2-B", "Google.es-US-Neural2-C", "Polly.Astrid", "Polly.Elin-Neural", "Google.sv-SE-Standard-A", "Google.sv-SE-Standard-B", "Google.sv-SE-Standard-C", "Google.sv-SE-Standard-D", "Google.sv-SE-Standard-E", "Google.sv-SE-Wavenet-A", "Google.sv-SE-Wavenet-B", "Google.sv-SE-Wavenet-C", "Google.sv-SE-Wavenet-D", "Google.sv-SE-Wavenet-E", "Google.ta-IN-Standard-C", "Google.ta-IN-Standard-D", "Google.ta-IN-Wavenet-C", "Google.ta-IN-Wavenet-D", "Google.te-IN-Standard-A", "Google.te-IN-Standard-B", "Google.th-TH-Standard-A", "Polly.Filiz", "Google.tr-TR-Standard-A", "Google.tr-TR-Standard-B", "Google.tr-TR-Standard-C", "Google.tr-TR-Standard-D", "Google.tr-TR-Standard-E", "Google.tr-TR-Wavenet-A", "Google.tr-TR-Wavenet-B", "Google.tr-TR-Wavenet-C", "Google.tr-TR-Wavenet-D", "Google.tr-TR-Wavenet-E", "Google.uk-UA-Standard-A", "Google.uk-UA-Wavenet-A", "Google.vi-VN-Standard-A", "Google.vi-VN-Standard-B", "Google.vi-VN-Standard-C", "Google.vi-VN-Standard-D", "Google.vi-VN-Wavenet-A", "Google.vi-VN-Wavenet-B", "Google.vi-VN-Wavenet-C", "Google.vi-VN-Wavenet-D", "Polly.Gwyneth"] # fmt:skip
+TWILIO_ASR_SUPPORTED_LANGUAGES = ["af-ZA", "am-ET", "hy-AM", "az-AZ", "id-ID", "ms-MY", "bn-BD", "bn-IN", "ca-ES", "cs-CZ", "da-DK", "de-DE", "en-AU", "en-CA", "en-GH", "en-GB", "en-IN", "en-IE", "en-KE", "en-NZ", "en-NG", "en-PH", "en-ZA", "en-TZ", "en-US", "es-AR", "es-BO", "es-CL", "es-CO", "es-CR", "es-EC", "es-SV", "es-ES", "es-US", "es-GT", "es-HN", "es-MX", "es-NI", "es-PA", "es-PY", "es-PE", "es-PR", "es-DO", "es-UY", "es-VE", "eu-ES", "fil-PH", "fr-CA", "fr-FR", "gl-ES", "ka-GE", "gu-IN", "hr-HR", "zu-ZA", "is-IS", "it-IT", "jv-ID", "kn-IN", "km-KH", "lo-LA", "lv-LV", "lt-LT", "hu-HU", "ml-IN", "mr-IN", "nl-NL", "ne-NP", "nb-NO", "pl-PL", "pt-BR", "pt-PT", "ro-RO", "si-LK", "sk-SK", "sl-SI", "su-ID", "sw-TZ", "sw-KE", "fi-FI", "sv-SE", "ta-IN", "ta-SG", "ta-LK", "ta-MY", "te-IN", "vi-VN", "tr-TR", "ur-PK", "ur-IN", "el-GR", "bg-BG", "ru-RU", "sr-RS", "uk-UA", "he-IL", "ar-IL", "ar-JO", "ar-AE", "ar-BH", "ar-DZ", "ar-SA", "ar-IQ", "ar-KW", "ar-MA", "ar-TN", "ar-OM", "ar-PS", "ar-QA", "ar-LB", "ar-EG", "fa-IR", "hi-IN", "th-TH", "ko-KR", "cmn-Hant-TW", "yue-Hant-HK", "ja-JP", "cmn-Hans-HK", "cmn-Hans-CN"] # fmt: skip
+
def general_integration_settings(bi: BotIntegration, current_user: AppUser):
if st.session_state.get(f"_bi_reset_{bi.id}"):
@@ -29,24 +33,21 @@ def general_integration_settings(bi: BotIntegration, current_user: AppUser):
st.session_state["analysis_urls"] = []
st.session_state.pop("--list-view:analysis_urls", None)
- bi.streaming_enabled = st.checkbox(
- "**📡 Streaming Enabled**",
- value=bi.streaming_enabled,
- key=f"_bi_streaming_enabled_{bi.id}",
- )
- st.caption("Responses will be streamed to the user in real-time if enabled.")
- bi.show_feedback_buttons = st.checkbox(
- "**👍🏾 👎🏽 Show Feedback Buttons**",
- value=bi.show_feedback_buttons,
- key=f"_bi_show_feedback_buttons_{bi.id}",
- )
- st.caption(
- "Users can rate and provide feedback on every copilot response if enabled."
- )
-
- st.caption(
- "Please note that this language is distinct from the one provided in the workflow settings. Hence, this allows you to integrate the same bot in many languages."
- )
+ if bi.platform != Platform.TWILIO:
+ bi.streaming_enabled = st.checkbox(
+ "**📡 Streaming Enabled**",
+ value=bi.streaming_enabled,
+ key=f"_bi_streaming_enabled_{bi.id}",
+ )
+ st.caption("Responses will be streamed to the user in real-time if enabled.")
+ bi.show_feedback_buttons = st.checkbox(
+ "**👍🏾 👎🏽 Show Feedback Buttons**",
+ value=bi.show_feedback_buttons,
+ key=f"_bi_show_feedback_buttons_{bi.id}",
+ )
+ st.caption(
+ "Users can rate and provide feedback on every copilot response if enabled."
+ )
st.write(
"""
@@ -128,6 +129,71 @@ def render_workflow_url_input(key: str, del_key: str | None, d: dict):
st.write("---")
+def twilio_specific_settings(bi: BotIntegration):
+ SETTINGS_FIELDS = ["twilio_use_missed_call", "twilio_initial_text", "twilio_initial_audio_url", "twilio_waiting_text", "twilio_waiting_audio_url", "twilio_tts_voice", "twilio_asr_language"] # fmt:skip
+ if st.session_state.get(f"_bi_reset_{bi.id}"):
+ for field in SETTINGS_FIELDS:
+ st.session_state[f"_bi_{field}_{bi.id}"] = BotIntegration._meta.get_field(
+ field
+ ).default
+
+ bi.twilio_tts_voice = (
+ st.selectbox(
+ "##### 🗣️ Twilio Voice",
+ options=TWILIO_SUPPORTED_VOICES,
+ value=bi.twilio_tts_voice,
+ format_func=lambda x: x.capitalize(),
+ key=f"_bi_twilio_tts_voice_{bi.id}",
+ )
+ or "Woman"
+ )
+ st.caption("Used when the underlying run does not have a Gooey TTS model enabled.")
+ bi.twilio_asr_language = (
+ st.selectbox(
+ "##### 🌐 Twilio ASR Language",
+ options=TWILIO_ASR_SUPPORTED_LANGUAGES,
+ key=f"_bi_twilio_asr_language_{bi.id}",
+ format_func=lambda x: langcodes.Language.get(x).display_name(),
+ value=bi.twilio_asr_language,
+ )
+ or "en-US"
+ )
+ st.caption("Used when the underlying run does not have a Gooey ASR model enabled.")
+ bi.twilio_initial_text = st.text_area(
+ "###### 📝 Initial Text (said at the beginning of each call)",
+ value=bi.twilio_initial_text,
+ key=f"_bi_twilio_initial_text_{bi.id}",
+ )
+ bi.twilio_initial_audio_url = (
+ st.file_uploader(
+ "###### 🔊 Initial Audio (played at the beginning of each call)",
+ accept=["audio/*"],
+ key=f"_bi_twilio_initial_audio_url_{bi.id}",
+ )
+ or ""
+ )
+ bi.twilio_waiting_audio_url = (
+ st.file_uploader(
+ "###### 🎵 Waiting Audio (played while waiting for a response -- Voice)",
+ accept=["audio/*"],
+ key=f"_bi_twilio_waiting_audio_url_{bi.id}",
+ )
+ or ""
+ )
+ bi.twilio_waiting_text = st.text_area(
+ "###### 📝 Waiting Text (texted while waiting for a response -- SMS)",
+ key=f"_bi_twilio_waiting_text_{bi.id}",
+ )
+ bi.twilio_use_missed_call = st.checkbox(
+ "📞 Use Missed Call",
+ value=bi.twilio_use_missed_call,
+ key=f"_bi_twilio_use_missed_call_{bi.id}",
+ )
+ st.caption(
+ "When enabled, immediately hangs up incoming calls and calls back the user so they don't incur charges (depending on their carrier/plan)."
+ )
+
+
def slack_specific_settings(bi: BotIntegration, default_name: str):
if st.session_state.get(f"_bi_reset_{bi.id}"):
st.session_state[f"_bi_name_{bi.id}"] = default_name
@@ -185,20 +251,30 @@ def broadcast_input(bi: BotIntegration):
optional=True,
accept=["audio/*"],
)
- video = st.file_uploader(
- "**🎥 Video**",
- key=key + ":video",
- help="Attach a video to this message.",
- optional=True,
- accept=["video/*"],
- )
- documents = st.file_uploader(
- "**📄 Documents**",
- key=key + ":documents",
- help="Attach documents to this message.",
- accept_multiple_files=True,
- optional=True,
- )
+ video = None
+ documents = None
+ medium = "Voice Call"
+ if bi.platform == Platform.TWILIO:
+ medium = st.selectbox(
+ "###### 📱 Medium",
+ ["Voice Call", "SMS/MMS"],
+ key=key + ":medium",
+ )
+ else:
+ video = st.file_uploader(
+ "**🎥 Video**",
+ key=key + ":video",
+ help="Attach a video to this message.",
+ optional=True,
+ accept=["video/*"],
+ )
+ documents = st.file_uploader(
+ "**📄 Documents**",
+ key=key + ":documents",
+ help="Attach documents to this message.",
+ accept_multiple_files=True,
+ optional=True,
+ )
should_confirm_key = key + ":should_confirm"
confirmed_send_btn = key + ":confirmed_send"
@@ -219,6 +295,7 @@ def broadcast_input(bi: BotIntegration):
documents=documents,
bi=bi,
convo_qs=convos,
+ medium=medium,
)
else:
if not convos.exists():
@@ -254,6 +331,8 @@ def get_bot_test_link(bi: BotIntegration) -> str | None:
integration_name=slugify(bi.name) or "untitled",
),
)
+ elif bi.twilio_phone_number_sid:
+ return f"https://console.twilio.com/us1/develop/phone-numbers/manage/incoming/{bi.twilio_phone_number_sid}/calls"
else:
return None
diff --git a/recipes/VideoBots.py b/recipes/VideoBots.py
index f8a3b8534..94eaec718 100644
--- a/recipes/VideoBots.py
+++ b/recipes/VideoBots.py
@@ -33,6 +33,7 @@
from daras_ai_v2.bot_integration_widgets import (
general_integration_settings,
slack_specific_settings,
+ twilio_specific_settings,
broadcast_input,
get_bot_test_link,
web_widget_config,
@@ -1248,6 +1249,12 @@ def render_integrations_settings(
unsafe_allow_html=True,
new_tab=True,
)
+ if bi.twilio_phone_number:
+ copy_to_clipboard_button(
+ f' Copy Phone Number',
+ value=bi.twilio_phone_number.as_e164,
+ type="secondary",
+ )
col1, col2 = st.columns(2, style={"alignItems": "center"})
with col1:
@@ -1267,6 +1274,8 @@ def render_integrations_settings(
unsafe_allow_html=True,
new_tab=True,
)
+ elif bi.platform == Platform.TWILIO and test_link:
+ pass
elif test_link:
st.anchor(
f"{icon} Message {bi.get_display_name()}",
@@ -1277,6 +1286,24 @@ def render_integrations_settings(
else:
st.write("Message quicklink not available.")
+ if bi.twilio_phone_number:
+ st.anchor(
+ ' Start Voice Call',
+ f"tel:{bi.twilio_phone_number.as_e164}",
+ unsafe_allow_html=True,
+ new_tab=True,
+ )
+ st.anchor(
+ ' Send SMS',
+ f"sms:{bi.twilio_phone_number.as_e164}",
+ unsafe_allow_html=True,
+ new_tab=True,
+ )
+ elif bi.platform == Platform.TWILIO:
+ st.write(
+ "Phone number incorrectly configured. Please re-add the integration and double check spelling. [Contact Us](support@gooey.ai) if you need help."
+ )
+
if bi.platform == Platform.WEB:
embed_code = get_web_widget_embed_code(bi)
copy_to_clipboard_button(
@@ -1305,6 +1332,13 @@ def render_integrations_settings(
),
new_tab=True,
)
+ if bi.platform == Platform.TWILIO and test_link:
+ st.anchor(
+ f"{icon} View Calls/Messages",
+ test_link,
+ unsafe_allow_html=True,
+ new_tab=True,
+ )
if bi.platform == Platform.WHATSAPP and bi.wa_business_waba_id:
col1, col2 = st.columns(2, style={"alignItems": "center"})
@@ -1339,9 +1373,11 @@ def render_integrations_settings(
with st.expander("Configure Settings 🛠️"):
if bi.platform == Platform.SLACK:
slack_specific_settings(bi, run_title)
+ if bi.platform == Platform.TWILIO:
+ twilio_specific_settings(bi)
general_integration_settings(bi, self.request.user)
- if bi.platform in [Platform.SLACK, Platform.WHATSAPP]:
+ if bi.platform in [Platform.SLACK, Platform.WHATSAPP, Platform.TWILIO]:
st.newline()
broadcast_input(bi)
st.write("---")