Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
rowanseymour committed Jun 25, 2024
1 parent bbc4658 commit fd73062
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 91 deletions.
6 changes: 3 additions & 3 deletions temba/channels/android/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def sync(request, channel_id):
if phone and text:
try:
msg_id = mailroom.get_client().android_message(
channel.org_id, channel.id, phone, text, received_on=date
channel.org, channel, phone, text, received_on=date
)
extra = dict(msg_id=msg_id)
except mailroom.URNValidationException:
Expand All @@ -162,8 +162,8 @@ def sync(request, channel_id):
if phone and call_tuple not in unique_calls and ChannelEvent.is_valid_type(cmd["type"]):
try:
mailroom.get_client().android_event(
channel.org_id,
channel.id,
channel.org,
channel,
phone,
cmd["type"],
extra={"duration": duration},
Expand Down
9 changes: 4 additions & 5 deletions temba/contacts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,12 +605,11 @@ def create(
fields_by_key = {f.key: v for f, v in fields.items()}
group_uuids = [g.uuid for g in groups]

response = mailroom.get_client().contact_create(
org.id,
user.id,
return mailroom.get_client().contact_create(
org,
user,
ContactSpec(name=name, language=language, urns=urns, fields=fields_by_key, groups=group_uuids),
)
return Contact.objects.get(id=response["contact"]["id"])

@property
def anon_display(self):
Expand Down Expand Up @@ -1815,7 +1814,7 @@ def write(self, export):
include_group_memberships = bool(len(group_fields) > 0)

if search:
contact_ids = mailroom.get_client().contact_export(export.org.id, group.id, query=search)["contact_ids"]
contact_ids = mailroom.get_client().contact_export(export.org, group, query=search)
else:
contact_ids = group.contacts.using("readonly").order_by("id").values_list("id", flat=True)

Expand Down
4 changes: 2 additions & 2 deletions temba/contacts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,8 @@ def get_blocker(self) -> str:
return blocker

query = self.request.GET.get("s")
preview = mailroom.get_client().contact_export_preview(self.request.org.id, self.group.id, query)
if preview["total"] > self.size_limit:
total = mailroom.get_client().contact_export_preview(self.request.org, self.group, query)
if total > self.size_limit:
return "too-big"

return ""
Expand Down
65 changes: 34 additions & 31 deletions temba/mailroom/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from django.conf import settings

from temba.contacts.models import Contact
from temba.utils import json

from ..modifiers import Modifier
Expand Down Expand Up @@ -33,7 +34,7 @@

class MailroomClient:
"""
Basic web client for mailroom
Client for mailroom HTTP endpoints
"""

default_headers = {"User-Agent": "Temba"}
Expand All @@ -47,43 +48,45 @@ def __init__(self, base_url, auth_token):
def version(self):
return self._request("", post=False).get("version")

def android_event(self, org_id: int, channel_id: int, phone: str, event_type: str, extra: dict, occurred_on):
payload = {
"org_id": org_id,
"channel_id": channel_id,
"phone": phone,
"event_type": event_type,
"extra": extra,
"occurred_on": occurred_on.isoformat(),
}

return self._request("android/event", payload)

def android_message(self, org_id: int, channel_id: int, phone: str, text: str, received_on):
payload = {
"org_id": org_id,
"channel_id": channel_id,
"phone": phone,
"text": text,
"received_on": received_on.isoformat(),
}
def android_event(self, org, channel, phone: str, event_type: str, extra: dict, occurred_on):
return self._request(
"android/event",
{
"org_id": org.id,
"channel_id": channel.id,
"phone": phone,
"event_type": event_type,
"extra": extra,
"occurred_on": occurred_on.isoformat(),
},
)

return self._request("android/message", payload)
def android_message(self, org, channel, phone: str, text: str, received_on):
return self._request(
"android/message",
{
"org_id": org.id,
"channel_id": channel.id,
"phone": phone,
"text": text,
"received_on": received_on.isoformat(),
},
)

def contact_create(self, org_id: int, user_id: int, contact: ContactSpec):
payload = {"org_id": org_id, "user_id": user_id, "contact": asdict(contact)}
def contact_create(self, org, user, contact: ContactSpec) -> Contact:
resp = self._request("contact/create", {"org_id": org.id, "user_id": user.id, "contact": asdict(contact)})

return self._request("contact/create", payload)
return Contact.objects.get(id=resp["contact"]["id"])

def contact_export(self, org_id: int, group_id: int, query: str):
payload = {"org_id": org_id, "group_id": group_id, "query": query}
def contact_export(self, org, group, query: str) -> list[int]:
resp = self._request("contact/export", {"org_id": org.id, "group_id": group.id, "query": query})

return self._request("contact/export", payload)
return resp["contact_ids"]

def contact_export_preview(self, org_id: int, group_id: int, query: str):
payload = {"org_id": org_id, "group_id": group_id, "query": query}
def contact_export_preview(self, org, group, query: str) -> int:
resp = self._request("contact/export_preview", {"org_id": org.id, "group_id": group.id, "query": query})

return self._request("contact/export_preview", payload)
return resp["total"]

def contact_inspect(self, org_id: int, contact_ids: list[int]):
payload = {"org_id": org_id, "contact_ids": contact_ids}
Expand Down
49 changes: 27 additions & 22 deletions temba/mailroom/client/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ def test_version(self):
def test_android_event(self, mock_post):
mock_post.return_value = MockJsonResponse(200, {"id": 12345})
response = self.client.android_event(
org_id=self.org.id,
channel_id=12,
org=self.org,
channel=self.channel,
phone="+1234567890",
event_type="mo_miss",
extra={"duration": 45},
Expand All @@ -52,7 +52,7 @@ def test_android_event(self, mock_post):
headers={"User-Agent": "Temba", "Authorization": "Token sesame"},
json={
"org_id": self.org.id,
"channel_id": 12,
"channel_id": self.channel.id,
"phone": "+1234567890",
"event_type": "mo_miss",
"extra": {"duration": 45},
Expand All @@ -64,8 +64,8 @@ def test_android_event(self, mock_post):
def test_android_message(self, mock_post):
mock_post.return_value = MockJsonResponse(200, {"id": 12345})
response = self.client.android_message(
org_id=self.org.id,
channel_id=12,
org=self.org,
channel=self.channel,
phone="+1234567890",
text="hello",
received_on=datetime(2024, 4, 1, 16, 28, 30, 0, tzone.utc),
Expand All @@ -78,7 +78,7 @@ def test_android_message(self, mock_post):
headers={"User-Agent": "Temba", "Authorization": "Token sesame"},
json={
"org_id": self.org.id,
"channel_id": 12,
"channel_id": self.channel.id,
"phone": "+1234567890",
"text": "hello",
"received_on": "2024-04-01T16:28:30+00:00",
Expand All @@ -87,14 +87,15 @@ def test_android_message(self, mock_post):

@patch("requests.post")
def test_contact_create(self, mock_post):
mock_post.return_value = MockJsonResponse(200, {"contact": {"id": 1234, "name": "", "language": ""}})
bob = self.create_contact("Bob", urns=["tel:+1234567890"])
mock_post.return_value = MockJsonResponse(200, {"contact": {"id": bob.id, "name": "Bob", "language": ""}})

# try with empty contact spec
response = self.client.contact_create(
self.org.id, self.admin.id, ContactSpec(name="", language="", urns=[], fields={}, groups=[])
contact = self.client.contact_create(
self.org, self.admin, ContactSpec(name="", language="", urns=[], fields={}, groups=[])
)

self.assertEqual({"id": 1234, "name": "", "language": ""}, response["contact"])
self.assertEqual(bob, contact)
mock_post.assert_called_once_with(
"http://localhost:8090/mr/contact/create",
headers={"User-Agent": "Temba", "Authorization": "Token sesame"},
Expand All @@ -106,11 +107,11 @@ def test_contact_create(self, mock_post):
)

mock_post.reset_mock()
mock_post.return_value = MockJsonResponse(200, {"contact": {"id": 1234, "name": "Bob", "language": "eng"}})
mock_post.return_value = MockJsonResponse(200, {"contact": {"id": bob.id, "name": "Bob", "language": "eng"}})

response = self.client.contact_create(
self.org.id,
self.admin.id,
contact = self.client.contact_create(
self.org,
self.admin,
ContactSpec(
name="Bob",
language="eng",
Expand All @@ -120,7 +121,7 @@ def test_contact_create(self, mock_post):
),
)

self.assertEqual({"id": 1234, "name": "Bob", "language": "eng"}, response["contact"])
self.assertEqual(bob, contact)
mock_post.assert_called_once_with(
"http://localhost:8090/mr/contact/create",
headers={"User-Agent": "Temba", "Authorization": "Token sesame"},
Expand All @@ -139,28 +140,30 @@ def test_contact_create(self, mock_post):

@patch("requests.post")
def test_contact_export(self, mock_post):
group = self.create_group("Doctors", contacts=[])
mock_post.return_value = MockJsonResponse(200, {"contact_ids": [123, 234]})

response = self.client.contact_export(self.org.id, 234, "age = 42")
response = self.client.contact_export(self.org, group, "age = 42")

self.assertEqual({"contact_ids": [123, 234]}, response)
self.assertEqual([123, 234], response)
mock_post.assert_called_once_with(
"http://localhost:8090/mr/contact/export",
headers={"User-Agent": "Temba", "Authorization": "Token sesame"},
json={"org_id": self.org.id, "group_id": 234, "query": "age = 42"},
json={"org_id": self.org.id, "group_id": group.id, "query": "age = 42"},
)

@patch("requests.post")
def test_contact_export_preview(self, mock_post):
group = self.create_group("Doctors", contacts=[])
mock_post.return_value = MockJsonResponse(200, {"total": 123})

response = self.client.contact_export_preview(self.org.id, 234, "age = 42")
total = self.client.contact_export_preview(self.org, group, "age = 42")

self.assertEqual({"total": 123}, response)
self.assertEqual(123, total)
mock_post.assert_called_once_with(
"http://localhost:8090/mr/contact/export_preview",
headers={"User-Agent": "Temba", "Authorization": "Token sesame"},
json={"org_id": self.org.id, "group_id": 234, "query": "age = 42"},
json={"org_id": self.org.id, "group_id": group.id, "query": "age = 42"},
)

@patch("requests.post")
Expand Down Expand Up @@ -675,7 +678,9 @@ def test_errors(self, mock_post):

with self.assertRaises(URNValidationException) as e:
self.client.contact_create(
1, 2, ContactSpec(name="Bob", language="eng", urns=["tel:+123456789"], fields={}, groups=[])
self.org,
self.admin,
ContactSpec(name="Bob", language="eng", urns=["tel:+123456789"], fields={}, groups=[]),
)

self.assertEqual("URN 1 is taken", e.exception.error)
Expand Down
43 changes: 15 additions & 28 deletions temba/tests/mailroom.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from temba import mailroom
from temba.campaigns.models import CampaignEvent, EventFire
from temba.channels.models import Channel, ChannelEvent
from temba.channels.models import ChannelEvent
from temba.contacts.models import URN, Contact, ContactField, ContactGroup, ContactURN
from temba.flows.models import FlowRun, FlowSession
from temba.locations.models import AdminBoundary
Expand Down Expand Up @@ -88,10 +88,10 @@ def mock(org, offset, sort):
self._contact_search[query] = mock

def contact_export(self, contact_ids: list[int]):
self._contact_export.append({"contact_ids": contact_ids})
self._contact_export.append(contact_ids)

def contact_export_preview(self, total: int):
self._contact_export_preview.append({"total": total})
self._contact_export_preview.append(total)

def contact_urns(self, urns: dict):
self._contact_urns.append(urns)
Expand Down Expand Up @@ -137,9 +137,7 @@ def __init__(self, mocks: Mocks):

super().__init__(settings.MAILROOM_URL, settings.MAILROOM_AUTH_TOKEN)

def android_event(self, org_id: int, channel_id: int, phone: str, event_type: str, extra: dict, occurred_on):
org = Org.objects.get(id=org_id)
channel = Channel.objects.get(id=channel_id)
def android_event(self, org, channel, phone: str, event_type: str, extra: dict, occurred_on):
contact, contact_urn = contact_resolve(org, phone)

event = ChannelEvent.objects.create(
Expand All @@ -153,9 +151,7 @@ def android_event(self, org_id: int, channel_id: int, phone: str, event_type: st
)
return {"id": event.id}

def android_message(self, org_id: int, channel_id: int, phone: str, text: str, received_on):
org = Org.objects.get(id=org_id)
channel = Channel.objects.get(id=channel_id)
def android_message(self, org, channel, phone: str, text: str, received_on):
contact, contact_urn = contact_resolve(org, phone)
text = text[: Msg.MAX_TEXT_LEN]

Expand All @@ -182,33 +178,24 @@ def android_message(self, org_id: int, channel_id: int, phone: str, text: str, r
return {"id": msg.id, "duplicate": False}

@_client_method
def contact_create(self, org_id: int, user_id: int, contact: mailroom.ContactSpec):
org = Org.objects.get(id=org_id)
user = User.objects.get(id=user_id)

obj = create_contact_locally(
def contact_create(self, org, user, contact: mailroom.ContactSpec):
return create_contact_locally(
org, user, contact.name, contact.language, contact.urns, contact.fields, contact.groups
)

return {"contact": {"id": obj.id, "uuid": str(obj.uuid), "name": obj.name}}

@_client_method
def contact_export_preview(self, org_id: int, group_id: int, query: str):
if self.mocks._contact_export_preview:
return self.mocks._contact_export_preview.pop(0)
def contact_export(self, org, group, query: str) -> list[int]:
if self.mocks._contact_export:
return self.mocks._contact_export.pop(0)

return {"total": ContactGroup.objects.get(id=group_id).get_member_count()}
return list(group.contacts.order_by("id").values_list("id", flat=True))

@_client_method
def contact_export(self, org_id: int, group_id: int, query: str):
if self.mocks._contact_export:
return self.mocks._contact_export.pop(0)
def contact_export_preview(self, org, group, query: str) -> int:
if self.mocks._contact_export_preview:
return self.mocks._contact_export_preview.pop(0)

return {
"contact_ids": list(
ContactGroup.objects.get(id=group_id).contacts.order_by("id").values_list("id", flat=True)
)
}
return group.get_member_count()

@_client_method
def contact_modify(self, org_id, user_id, contact_ids, modifiers: list[Modifier]):
Expand Down

0 comments on commit fd73062

Please sign in to comment.