From 621bb31f0570f9ac81ede3c2bf178bc58ba66098 Mon Sep 17 00:00:00 2001 From: Rudi Giesler Date: Wed, 21 Dec 2022 17:52:27 +0200 Subject: [PATCH 1/3] Add scripts for fetching/extracting contacts from RapidPro, and uploading to Turn --- .../extract_rapidpro_group.py | 50 +++++++++++++++++++ .../extract_whatsapp_id_from_excel_export.py | 27 ++++++++++ .../set_turn_contact_field.py | 45 +++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 scripts/rapidpro_to_turn/extract_rapidpro_group.py create mode 100644 scripts/rapidpro_to_turn/extract_whatsapp_id_from_excel_export.py create mode 100644 scripts/rapidpro_to_turn/set_turn_contact_field.py diff --git a/scripts/rapidpro_to_turn/extract_rapidpro_group.py b/scripts/rapidpro_to_turn/extract_rapidpro_group.py new file mode 100644 index 00000000..64da9738 --- /dev/null +++ b/scripts/rapidpro_to_turn/extract_rapidpro_group.py @@ -0,0 +1,50 @@ +import argparse +from urllib.parse import urlencode, urljoin + +import requests + + +def get_arguments(): + parser = argparse.ArgumentParser( + description="Fetches all the whatsapp IDs of a group of contacts" + ) + parser.add_argument( + "--url", + help="The base URL for the rapidpro instance", + default="https://rapidpro.prd.momconnect.co.za/", + ) + parser.add_argument("token", help="Authorization token for RapidPro") + parser.add_argument("group", help="The group to fetch contacts for") + return parser.parse_args() + + +def format_urn(urn: str): + _, path = urn.split(":") + return path + + +def fetch_contacts(url, token, group): + url = urljoin(url, "/api/v2/contacts.json") + query = urlencode({"group": group}) + next_ = f"{url}?{query}" + + while next_: + response = requests.get( + next_, + headers={"Authorization": f"Token {token}", "Accept": "application/json"}, + ) + response.raise_for_status() + result = response.json() + next_ = result["next"] + for contact in result["results"]: + if contact["urns"]: + print(format_urn(contact["urns"][0])) + + +def main(): + args = get_arguments() + fetch_contacts(args.url, args.token, args.group) + + +if __name__ == "__main__": + main() diff --git a/scripts/rapidpro_to_turn/extract_whatsapp_id_from_excel_export.py b/scripts/rapidpro_to_turn/extract_whatsapp_id_from_excel_export.py new file mode 100644 index 00000000..01d56394 --- /dev/null +++ b/scripts/rapidpro_to_turn/extract_whatsapp_id_from_excel_export.py @@ -0,0 +1,27 @@ +import argparse +from openpyxl import load_workbook + +def get_arguments(): + parser = argparse.ArgumentParser( + description="Extracts the whatsapp IDs from a rapidpro contacts export" + ) + parser.add_argument("filename", help="Excel file to extract from") + return parser.parse_args() + +def main(): + args = get_arguments() + wb = load_workbook(args.filename, read_only=True) + ws = wb.active + for row in ws.iter_rows(min_row=1, max_row=1): + for cell in row: + if cell.value == "URN:Whatsapp": + urn_col = cell.column + break + break + for row in ws.iter_rows(min_row=2): + whatsapp_id = row[urn_col - 1].value + if whatsapp_id and whatsapp_id.isnumeric(): + print(whatsapp_id) + +if __name__ == "__main__": + main() diff --git a/scripts/rapidpro_to_turn/set_turn_contact_field.py b/scripts/rapidpro_to_turn/set_turn_contact_field.py new file mode 100644 index 00000000..67a1e230 --- /dev/null +++ b/scripts/rapidpro_to_turn/set_turn_contact_field.py @@ -0,0 +1,45 @@ +import argparse +import requests +from urllib.parse import urljoin +import sys + + +def get_arguments(): + parser = argparse.ArgumentParser( + description="Updates a contact field in Turn for all whatsapp IDs on stdin" + ) + parser.add_argument( + "--url", + help="The base URL for the Turn instance", + default="https://whatsapp-praekelt-cloud.turn.io/", + ) + parser.add_argument("token", help="Authorization token for Turn") + parser.add_argument("field", help="The contact field to set") + parser.add_argument("value", help="The value to set the contact field to") + return parser.parse_args() + + +def update_contact(url, token, field, value, whatsapp_id): + url = urljoin(url, f"/v1/contacts/{whatsapp_id}/profile") + response = requests.patch( + url, + json={field: value}, + headers={ + "Accept": "application/vnd.v1+json", + "Authorization": f"Bearer {token}", + }, + ) + if not response.ok: + print(f"Error updating {whatsapp_id}") + print(response.status_code) + print(response.text) + else: + print(f"Updated {whatsapp_id}") + +def main(): + args = get_arguments() + for line in sys.stdin: + update_contact(args.url, args.token, args.field, args.value, line.strip()) + +if __name__ == "__main__": + main() From 277c6b18fe07cbf099209ffe034e3677665625c1 Mon Sep 17 00:00:00 2001 From: Rudi Giesler Date: Wed, 21 Dec 2022 17:55:10 +0200 Subject: [PATCH 2/3] Linting --- .../rapidpro_to_turn/extract_whatsapp_id_from_excel_export.py | 3 +++ scripts/rapidpro_to_turn/set_turn_contact_field.py | 2 ++ 2 files changed, 5 insertions(+) diff --git a/scripts/rapidpro_to_turn/extract_whatsapp_id_from_excel_export.py b/scripts/rapidpro_to_turn/extract_whatsapp_id_from_excel_export.py index 01d56394..5992e05d 100644 --- a/scripts/rapidpro_to_turn/extract_whatsapp_id_from_excel_export.py +++ b/scripts/rapidpro_to_turn/extract_whatsapp_id_from_excel_export.py @@ -1,6 +1,7 @@ import argparse from openpyxl import load_workbook + def get_arguments(): parser = argparse.ArgumentParser( description="Extracts the whatsapp IDs from a rapidpro contacts export" @@ -8,6 +9,7 @@ def get_arguments(): parser.add_argument("filename", help="Excel file to extract from") return parser.parse_args() + def main(): args = get_arguments() wb = load_workbook(args.filename, read_only=True) @@ -23,5 +25,6 @@ def main(): if whatsapp_id and whatsapp_id.isnumeric(): print(whatsapp_id) + if __name__ == "__main__": main() diff --git a/scripts/rapidpro_to_turn/set_turn_contact_field.py b/scripts/rapidpro_to_turn/set_turn_contact_field.py index 67a1e230..7d57d4d3 100644 --- a/scripts/rapidpro_to_turn/set_turn_contact_field.py +++ b/scripts/rapidpro_to_turn/set_turn_contact_field.py @@ -36,10 +36,12 @@ def update_contact(url, token, field, value, whatsapp_id): else: print(f"Updated {whatsapp_id}") + def main(): args = get_arguments() for line in sys.stdin: update_contact(args.url, args.token, args.field, args.value, line.strip()) + if __name__ == "__main__": main() From 3ff42cb351d4354bbff9feaf2f92cfdb125637b8 Mon Sep 17 00:00:00 2001 From: Rudi Giesler Date: Wed, 21 Dec 2022 17:58:20 +0200 Subject: [PATCH 3/3] Sort imports --- .../extract_whatsapp_id_from_excel_export.py | 1 + scripts/rapidpro_to_turn/set_turn_contact_field.py | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/rapidpro_to_turn/extract_whatsapp_id_from_excel_export.py b/scripts/rapidpro_to_turn/extract_whatsapp_id_from_excel_export.py index 5992e05d..c957766e 100644 --- a/scripts/rapidpro_to_turn/extract_whatsapp_id_from_excel_export.py +++ b/scripts/rapidpro_to_turn/extract_whatsapp_id_from_excel_export.py @@ -1,4 +1,5 @@ import argparse + from openpyxl import load_workbook diff --git a/scripts/rapidpro_to_turn/set_turn_contact_field.py b/scripts/rapidpro_to_turn/set_turn_contact_field.py index 7d57d4d3..4a55c274 100644 --- a/scripts/rapidpro_to_turn/set_turn_contact_field.py +++ b/scripts/rapidpro_to_turn/set_turn_contact_field.py @@ -1,7 +1,8 @@ import argparse -import requests -from urllib.parse import urljoin import sys +from urllib.parse import urljoin + +import requests def get_arguments():