def search_contacts(org, query: str, *, group=None, sort: str = None, offset: int = None, exclude_ids=()) -> SearchResults: try: group_uuid = group.uuid if group else None response = mailroom.get_client().contact_search( org.id, group_uuid=str(group_uuid), query=query, sort=sort, offset=offset, exclude_ids=exclude_ids, ) return SearchResults( response["total"], response["query"], response["contact_ids"], Metadata(**response.get("metadata", {})), ) except mailroom.MailroomException as e: raise SearchException.from_mailroom_exception(e)
def populate_flow_metadata(apps, schema_editor): Flow = apps.get_model("flows", "Flow") FlowRevision = apps.get_model("flows", "FlowRevision") client = mailroom.get_client() num_updated = 0 for flow in Flow.objects.filter(is_active=True): # get our last revision revision = FlowRevision.objects.filter( flow=flow).order_by("-revision").first() # validate it try: validated_definition = client.flow_validate( None, revision.definition) flow.metadata = { "results": validated_definition["_results"], "dependencies": validated_definition["_dependencies"], "waiting_exit_uuids": validated_definition["_waiting_exits"], } flow.save(update_fields=["metadata"]) except mailroom.FlowValidationException as e: print(f"Error validating flow: {flow.id} - {e}") num_updated += 1 if num_updated % 1000 == 0: print(f"Updated metadata for {num_updated} flows") if num_updated > 0: print(f"Updated metadata for {num_updated} flows")
def inspect_flows(): client = mailroom.get_client() num_inspected = 0 num_updated = 0 num_invalid = 0 for flow in Flow.objects.filter(is_active=True).order_by("id"): try: flow_info = client.flow_inspect(flow.org_id, flow.get_definition()) except FlowValidationException: num_invalid += 1 continue finally: num_inspected += 1 has_issues = len(flow_info["issues"]) > 0 if has_issues != flow.has_issues: flow.has_issues = has_issues flow.save(update_fields=("has_issues", )) num_updated += 1 if num_inspected % 100 == 0: # pragma: no cover print( f" > Flows inspected: {num_inspected}, updated: {num_updated}, invalid: {num_invalid}" ) print( f"Total flows inspected: {num_inspected}, updated: {num_updated}, invalid: {num_invalid}" )
def bulk_assign(cls, org, user: User, tickets: list, assignee: User, note: str = None): ticket_ids = [t.id for t in tickets if t.ticketer.is_active] assignee_id = assignee.id if assignee else None return mailroom.get_client().ticket_assign(org.id, user.id, ticket_ids, assignee_id, note)
def serialize_flow(flow): """ Migrates the given flow, returning None if the flow or any of its dependencies can't be run in goflow because of unsupported features. """ flow.ensure_current_version() flow_def = flow.as_json(expand_contacts=True) return mailroom.get_client().flow_migrate({"flow": flow_def, "collapse_exits": False})
def parse_query(org, query: str, *, group=None) -> ParsedQuery: """ Parses the passed in query in the context of the org """ try: group_uuid = group.uuid if group else None response = mailroom.get_client().parse_query(org.id, query, group_uuid=str(group_uuid)) return ParsedQuery(response["query"], response["elastic_query"], Metadata(**response.get("metadata", {}))) except mailroom.MailroomException as e: raise SearchException.from_mailroom_exception(e)
def serialize_flow(flow): """ Migrates the given flow, returning None if the flow or any of its dependencies can't be run in goflow because of unsupported features. """ flow.ensure_current_version() flow_def = flow.as_json(expand_contacts=True) return mailroom.get_client().flow_migrate({ "flow": flow_def, "collapse_exits": False })
def parse_query(org_id, query, group_uuid=""): """ Parses the passed in query in the context of the org """ try: client = mailroom.get_client() response = client.parse_query(org_id, query, group_uuid=str(group_uuid)) return ParsedQuery(response["query"], response["fields"], response["elastic_query"], response.get("allow_as_group", False)) except mailroom.MailroomException as e: raise SearchException(e.response["error"])
def search_contacts(org_id, group_uuid, query, sort=None, offset=None): try: client = mailroom.get_client() response = client.contact_search(org_id, str(group_uuid), query, sort, offset=offset) return SearchResults( response["total"], response["query"], response["contact_ids"], Metadata(**response.get("metadata", {})), ) except mailroom.MailroomException as e: raise SearchException.from_mailroom_exception(e)
def parse_query(org_id, query, group_uuid=""): """ Parses the passed in query in the context of the org """ try: client = mailroom.get_client() response = client.parse_query(org_id, query, group_uuid=str(group_uuid)) return ParsedQuery( response["query"], response["elastic_query"], Metadata(**response.get("metadata", {})), ) except mailroom.MailroomException as e: raise SearchException.from_mailroom_exception(e)
def search_contacts(org_id, group_uuid, query, sort=None, offset=None): try: client = mailroom.get_client() response = client.contact_search(org_id, str(group_uuid), query, sort, offset=offset) return SearchResults( response["total"], response["query"], response["fields"], response.get("allow_as_group", False), response["contact_ids"], ) except mailroom.MailroomException as e: raise SearchException(e.response["error"])
def bulk_reopen(cls, org, tickets): return mailroom.get_client().ticket_reopen( org.id, [t.id for t in tickets if t.ticketer.is_active])
def migrate_translations(translations): return { lang: mailroom.get_client().expression_migrate(s) for lang, s in translations.items() }
def bulk_reopen(cls, org, user, tickets): ticket_ids = [t.id for t in tickets if t.ticketer.is_active] return mailroom.get_client().ticket_reopen(org.id, user.id, ticket_ids)
def bulk_close(cls, org, user, tickets, *, force: bool = False): ticket_ids = [t.id for t in tickets if t.ticketer.is_active] return mailroom.get_client().ticket_close(org.id, user.id, ticket_ids, force=force)
def bulk_change_topic(cls, org, user: User, tickets: list, topic: Topic): ticket_ids = [t.id for t in tickets if t.ticketer.is_active] return mailroom.get_client().ticket_change_topic( org.id, user.id, ticket_ids, topic.id)
def bulk_add_note(cls, org, user: User, tickets: list, note: str): ticket_ids = [t.id for t in tickets if t.ticketer.is_active] return mailroom.get_client().ticket_add_note(org.id, user.id, ticket_ids, note)
def backfill_flow_deps(Flow, Channel, Label): FlowChannelDeps = Flow.channel_dependencies.through FlowLabelDeps = Flow.label_dependencies.through flows_qs = Flow.objects.filter(is_active=True) total_count = flows_qs.count() print(f"Found {total_count} flows with missing channel and label deps...") num_updated = 0 total_added_channels = 0 total_added_labels = 0 invalid_flow_ids = set() with transaction.atomic(): for flow_id, org_id, revision, flow_definition in latest_flow_revisions( ): # validate flow try: validated = mailroom.get_client().flow_validate( None, json.loads(flow_definition)) except MailroomException: invalid_flow_ids.add(flow_id) continue # skip error dependencies = validated["_dependencies"] channel_uuids = [ g["uuid"] for g in dependencies.get("channels", []) ] label_uuids = [g["uuid"] for g in dependencies.get("labels", [])] channel_ids = Channel.objects.filter(org_id=org_id, uuid__in=channel_uuids, is_active=True).values_list( "id", flat=True) label_ids = Label.all_objects.filter(label_type="L", org_id=org_id, uuid__in=label_uuids, is_active=True).values_list( "id", flat=True) # channels FlowChannelDeps.objects.filter(flow_id=flow_id).delete() bulk_chan_deps_to_add = [ FlowChannelDeps(flow_id=flow_id, channel_id=chan_id) for chan_id in channel_ids ] FlowChannelDeps.objects.bulk_create(bulk_chan_deps_to_add) total_added_channels += len(bulk_chan_deps_to_add) # labels FlowLabelDeps.objects.filter(flow_id=flow_id).delete() bulk_label_deps_to_add = [ FlowLabelDeps(flow_id=flow_id, label_id=label_id) for label_id in label_ids ] FlowLabelDeps.objects.bulk_create(bulk_label_deps_to_add) total_added_labels += len(bulk_label_deps_to_add) num_updated += 1 if num_updated % 1000 == 0: print( f" > Updated {num_updated} of {total_count} flows, invalid flows {len(invalid_flow_ids)}, c:{total_added_channels} l:{total_added_labels}" ) if num_updated: print( f" > Updated {num_updated} of {total_count} flows, invalid flows {len(invalid_flow_ids)}, c:{total_added_channels} l:{total_added_labels}" )