-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sureadhere messaging provider integrated #390
base: main
Are you sure you want to change the base?
Conversation
# Conflicts resolved: # apps/channels/models.py # apps/channels/tasks.py
@cws1121 - can you run |
apps/channels/models.py
Outdated
|
||
|
||
class ChannelPlatform(models.TextChoices): | ||
TELEGRAM = "telegram", "Telegram" | ||
WEB = "web", "Web" | ||
WHATSAPP = "whatsapp", "WhatsApp" | ||
FACEBOOK = "facebook", "Facebook" | ||
IN_APP = "in_app", "In App" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change the name of this:
IN_APP = "in_app", "In App" | |
SUREADHERE = "sureadhere", "SureAdhere" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also any other references e.g. InAppChannelForm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, I've renamed everything to SureAdhere as suggested. However, I'm not entirely convinced this is the best way to go. While SureAdhere is one of the in-app messaging platforms we currently support, what if we decide to add another provider in the future that also offers in-app messaging capabilities? For instance, we already have both Twilio and Turn.io listed under the "whatsapp" option, even though they are separate providers for the WhatsApp channel.That said perhaps it would be better to keep the more generic "in_app" naming convention. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While SureAdhere is one of the in-app messaging platforms we currently support, what if we decide to add another provider in the future that also offers in-app messaging capabilities?
I'm not sure I quite follow this. If SA adds support for another provider e.g. telegram then OCS will still want to use the SA channel and SA will decide how to deliver that message to the user based on what provider that user is using to communicate with. But OCS won't know about the different downstream providers will it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I mentioned adding another provider in the future, I was referring to the possibility of OCS itself integrating with another in-app messaging platform similar to SureAdhere, not SureAdhere adding support for another provider.
The concern I raised was that if we rename everything to be specific to SureAdhere, it might make it more difficult to integrate with a different in-app messaging platform in the future, should the need arise. By keeping the naming convention more generic (e.g., InAppChannelForm), it would be easier to accommodate additional in-app messaging providers without having to rename everything again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like we're missing eachother somewhere and maybe we should go to voice but I'll take one more go at explaining what I think.
When you say "in app", do you mean "communication through a mobile app"? Is that not what WhatsApp and Telegram are already?
In terms of this data model, a channel type should be 1-1 with how the user access it e.g. whatsapp vs telegram vs sureadhere
The MessagingProvider
ties the channels to a way of sending and receiving messages and is 1-many since the same provider could facilitate communications on multiple channels and multiple providers can support the same channel.
If we take WhatsApp as an example, both Turn and Twilio provide WhatsApp messaging capabilities but which one the user chooses depends on which provider they are using.
If you still have doubts, let's schedule a call.
return response.json()["access_token"] | ||
|
||
def send_text_message(self, message: str, to: str, platform: ChannelPlatform, from_: str = None): | ||
access_token = self.get_access_token() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way we could reuse these? How long do they last for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the token is valid for 1 hour. I'll double check that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the documentation, we could increase that to 24 hours (the upper limit).
apps/channels/forms.py
Outdated
@@ -71,6 +71,33 @@ def get_success_message(self, channel: ExperimentChannel): | |||
return f"Use the following URL when setting up the webhook: {channel.webhook_url}" | |||
|
|||
|
|||
class InAppChannelForm(ExtraFormBase): | |||
client_id = forms.CharField(label="Client ID", max_length=100) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this client_id
different from the one on the MessagingProvider
. If they are the same the it doesn't seem useful to have it here as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it's a different, it refers to the ID of the SureAdhere client (workspace). This field acts as a unique key (channel_identifier_key property of the ChannelPlatform)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you confirm this understanding:
MessagingProvider.client_id
: this is an Oauth client ID used to authenticate with SureAdhereChannel.client_id
: this is a workspace ID in SureAdhere (is a workspace SureAdhere's 'tenent'?)
Is Client ID
the right name for it then?
It's also not clear to me what this is used for since it isn't included in the requests to send messages so it appears to only be used for the webhook.
I think that leads to the question of how the webhooks in SA are configured. Is there documentation on that somewhere? How does SA know which webhook to call for a specific message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I can confirm your understanding of the parameter names.
We can rename that parameter to sureadhere_client_id perhaps?
Initially, I was using client_id (the SureAdhere tenant ID) for the webhook configuration. However, based on your suggestion, I've replaced it with channel_external_id. At the moment, client_id is only being used to distinguish different SureAdhere channels on OCS.
As per my understanding channels need to have a variable as unique identifier (I am referring to channel_identifier_key -> 8a0f7b3#diff-e86734efa3030e0fee86bb735b2db59c0349a54045cc1a0b48d3b187b82d722bR61)
There is no documentation available on how the webhooks in SureAdhere are configured. Currently, we only have one hardcoded webhook on staging that we're using for testing purposes. This is still an open question, and I haven't received clear instructions from the product team on how that part of the integration is supposed to work. Here are a few thoughts based on the potential scenarios:
If SureAdhere provides an interface where we can assign webhooks for each client (tenant), then the current implementation of using channel_external_id for the webhook configuration seems like a reasonable approach.
However, if SureAdhere is expected to know which OCS webhook to use when forwarding client messages (without any configuration), then it would be a good idea to revert channel_external_id back to client_id in the OCS webhook URLs. Does that sound reasonable to you?
I'll follow up with the product team tomorrow to get more clarity on how the SureAdhere integration is intended to work and how the webhooks should be configured.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typically webhooks are configured in the sending system so that it know where to send messages. There are 2 options:
- A generic webhook where the request body contains some information that identifies where the message is coming from e.g. client_id
- A webhook that contains some identifying info in it e.g. experiment_id or client_id
Either of these approaches are fine but both require some way to configure them in SA.
For now we can revert to using client_id
since that's what allows you to test but I'd like to hear what the product team has to say.
apps/channels/forms.py
Outdated
@@ -71,6 +71,33 @@ def get_success_message(self, channel: ExperimentChannel): | |||
return f"Use the following URL when setting up the webhook: {channel.webhook_url}" | |||
|
|||
|
|||
class InAppChannelForm(ExtraFormBase): | |||
client_id = forms.CharField(label="Client ID", max_length=100) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you confirm this understanding:
MessagingProvider.client_id
: this is an Oauth client ID used to authenticate with SureAdhereChannel.client_id
: this is a workspace ID in SureAdhere (is a workspace SureAdhere's 'tenent'?)
Is Client ID
the right name for it then?
It's also not clear to me what this is used for since it isn't included in the requests to send messages so it appears to only be used for the webhook.
I think that leads to the question of how the webhooks in SA are configured. Is there documentation on that somewhere? How does SA know which webhook to call for a specific message?
apps/channels/models.py
Outdated
|
||
|
||
class ChannelPlatform(models.TextChoices): | ||
TELEGRAM = "telegram", "Telegram" | ||
WEB = "web", "Web" | ||
WHATSAPP = "whatsapp", "WhatsApp" | ||
FACEBOOK = "facebook", "Facebook" | ||
IN_APP = "in_app", "In App" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While SureAdhere is one of the in-app messaging platforms we currently support, what if we decide to add another provider in the future that also offers in-app messaging capabilities?
I'm not sure I quite follow this. If SA adds support for another provider e.g. telegram then OCS will still want to use the SA channel and SA will decide how to deliver that message to the user based on what provider that user is using to communicate with. But OCS won't know about the different downstream providers will it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all the updates. This is very close now. I think there are only 2 outstanding things I'd like addressed before approval:
- Revert the webhook to use
client_id
so that you can continue testing - Add help text to
SureAdhereChannelForm.client_id
indicating what it is
PLATFORM = ( | ||
(TELEGRAM, "Telegram"), | ||
(WEB, "Web"), | ||
(WHATSAPP, "WhatsApp"), | ||
(FACEBOOK, "Facebook"), | ||
(SUREADHERE, "SureAdhere"), | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesn't appear to be used anywhere so you could delete it
return f"Use the following URL when setting up the webhook: {channel.webhook_url}" | ||
|
||
class SureAdhereChannelForm(WebhookUrlFormBase): | ||
client_id = forms.CharField(label="Client ID", max_length=100) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add some help text here assist the user in understanding what this field is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between this client_id
field and the client_id
field from the SureAdhereService
? This client id identifies a SureAdhere "project" so to speak whereas the other client id is an Azure id, yes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I just saw this comment explaining the difference
@@ -50,12 +54,29 @@ def handle_twilio_message(self, message_data: str): | |||
extra_data__contains={channel_id_key: message.to}, messaging_provider__type=MessagingProviderType.twilio | |||
).first() | |||
if not experiment_channel: | |||
logger.info(f"No experiment channel found for {channel_id_key}: {message.to}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
No description provided.