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 99c8884
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 117 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
17 changes: 7 additions & 10 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 @@ -997,8 +996,8 @@ def interrupt(self, user) -> bool:
Interrupts this contact's current flow
"""
if self.current_flow:
sessions = mailroom.get_client().contact_interrupt(self.org.id, user.id, self.id)
return len(sessions) > 0
return mailroom.get_client().contact_interrupt(self.org, user, self) > 0

return False

def block(self, user):
Expand Down Expand Up @@ -1160,9 +1159,7 @@ def bulk_inspect(self, contacts) -> dict:
if not contacts:
return {}

resp = mailroom.get_client().contact_inspect(contacts[0].org_id, [c.id for c in contacts])

return {c: resp[str(c.id)] for c in contacts}
return mailroom.get_client().contact_inspect(contacts[0].org, contacts)

def get_groups(self, *, manual_only=False):
"""
Expand Down Expand Up @@ -1815,7 +1812,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
77 changes: 40 additions & 37 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,53 +48,55 @@ 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}
def contact_inspect(self, org, contacts) -> dict:
resp = self._request("contact/inspect", {"org_id": org.id, "contact_ids": [c.id for c in contacts]})

return self._request("contact/inspect", payload)
return {c: resp[str(c.id)] for c in contacts}

def contact_interrupt(self, org_id: int, user_id: int, contact_id: int):
payload = {"org_id": org_id, "user_id": user_id, "contact_id": contact_id}
def contact_interrupt(self, org, user, contact) -> int:
resp = self._request("contact/interrupt", {"org_id": org.id, "user_id": user.id, "contact_id": contact.id})

return self._request("contact/interrupt", payload)
return resp["sessions"]

def contact_modify(self, org_id: int, user_id: int, contact_ids: list[int], modifiers: list[Modifier]):
payload = {
Expand Down
67 changes: 38 additions & 29 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,16 @@ 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": ""}})
ann = self.create_contact("Ann", urns=["tel:+12340000001"])
bob = self.create_contact("Bob", urns=["tel:+12340000002"])
mock_post.return_value = MockJsonResponse(200, {"contact": {"id": ann.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(ann, contact)
mock_post.assert_called_once_with(
"http://localhost:8090/mr/contact/create",
headers={"User-Agent": "Temba", "Authorization": "Token sesame"},
Expand All @@ -106,11 +108,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 +122,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,54 +141,59 @@ 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")
def test_contact_inspect(self, mock_post):
mock_post.return_value = MockJsonResponse(200, {"101": {}, "102": {}})
ann = self.create_contact("Ann", urns=["tel:+12340000001"])
bob = self.create_contact("Bob", urns=["tel:+12340000002"])
mock_post.return_value = MockJsonResponse(200, {ann.id: {}, bob.id: {}})

response = self.client.contact_inspect(self.org.id, [101, 102])
response = self.client.contact_inspect(self.org, [ann, bob])

self.assertEqual({"101": {}, "102": {}}, response)
self.assertEqual({ann: {}, bob: {}}, response)
mock_post.assert_called_once_with(
"http://localhost:8090/mr/contact/inspect",
headers={"User-Agent": "Temba", "Authorization": "Token sesame"},
json={"org_id": self.org.id, "contact_ids": [101, 102]},
json={"org_id": self.org.id, "contact_ids": [ann.id, bob.id]},
)

@patch("requests.post")
def test_contact_interrupt(self, mock_post):
ann = self.create_contact("Ann", urns=["tel:+12340000001"])
mock_post.return_value = MockJsonResponse(200, {"sessions": 1})

response = self.client.contact_interrupt(self.org.id, 3, 345)
response = self.client.contact_interrupt(self.org, self.admin, ann)

self.assertEqual({"sessions": 1}, response)
self.assertEqual(1, response)
mock_post.assert_called_once_with(
"http://localhost:8090/mr/contact/interrupt",
headers={"User-Agent": "Temba", "Authorization": "Token sesame"},
json={"org_id": self.org.id, "user_id": 3, "contact_id": 345},
json={"org_id": self.org.id, "user_id": self.admin.id, "contact_id": ann.id},
)

def test_contact_modify(self):
Expand Down Expand Up @@ -675,7 +682,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
Loading

0 comments on commit 99c8884

Please sign in to comment.