Suraj Shetty | 863b93c | 2019-05-21 07:57:06 +0530 | [diff] [blame] | 1 | import frappe |
Suraj Shetty | 1eeb89f | 2019-05-22 06:37:43 +0530 | [diff] [blame] | 2 | import requests |
| 3 | |
| 4 | # api/method/erpnext.erpnext_integrations.exotel_integration.handle_incoming_call |
Suraj Shetty | c8c1742 | 2019-06-07 10:22:50 +0530 | [diff] [blame] | 5 | # api/method/erpnext.erpnext_integrations.exotel_integration.handle_end_call |
| 6 | # api/method/erpnext.erpnext_integrations.exotel_integration.handle_missed_call |
Suraj Shetty | 863b93c | 2019-05-21 07:57:06 +0530 | [diff] [blame] | 7 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 8 | |
Suraj Shetty | 863b93c | 2019-05-21 07:57:06 +0530 | [diff] [blame] | 9 | @frappe.whitelist(allow_guest=True) |
Suraj Shetty | 502565f | 2019-07-01 14:28:59 +0530 | [diff] [blame] | 10 | def handle_incoming_call(**kwargs): |
Suraj Shetty | af2eac4 | 2019-09-17 15:53:23 +0530 | [diff] [blame] | 11 | try: |
| 12 | exotel_settings = get_exotel_settings() |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 13 | if not exotel_settings.enabled: |
| 14 | return |
Suraj Shetty | 863b93c | 2019-05-21 07:57:06 +0530 | [diff] [blame] | 15 | |
Suraj Shetty | af2eac4 | 2019-09-17 15:53:23 +0530 | [diff] [blame] | 16 | call_payload = kwargs |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 17 | status = call_payload.get("Status") |
| 18 | if status == "free": |
Suraj Shetty | af2eac4 | 2019-09-17 15:53:23 +0530 | [diff] [blame] | 19 | return |
Suraj Shetty | 07fe299 | 2019-05-22 15:48:57 +0530 | [diff] [blame] | 20 | |
Suraj Shetty | af2eac4 | 2019-09-17 15:53:23 +0530 | [diff] [blame] | 21 | call_log = get_call_log(call_payload) |
| 22 | if not call_log: |
| 23 | create_call_log(call_payload) |
| 24 | else: |
| 25 | update_call_log(call_payload, call_log=call_log) |
| 26 | except Exception as e: |
| 27 | frappe.db.rollback() |
Rushabh Mehta | 548afba | 2022-05-02 15:04:26 +0530 | [diff] [blame] | 28 | exotel_settings.log_error("Error in Exotel incoming call") |
Suraj Shetty | 122f1c0 | 2022-08-24 18:24:39 +0530 | [diff] [blame] | 29 | frappe.db.commit() |
Suraj Shetty | 07fe299 | 2019-05-22 15:48:57 +0530 | [diff] [blame] | 30 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 31 | |
Suraj Shetty | bd03a51 | 2019-05-27 15:30:41 +0530 | [diff] [blame] | 32 | @frappe.whitelist(allow_guest=True) |
Suraj Shetty | 502565f | 2019-07-01 14:28:59 +0530 | [diff] [blame] | 33 | def handle_end_call(**kwargs): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 34 | update_call_log(kwargs, "Completed") |
| 35 | |
Suraj Shetty | e9bfecf | 2019-06-03 12:27:02 +0530 | [diff] [blame] | 36 | |
| 37 | @frappe.whitelist(allow_guest=True) |
Suraj Shetty | 502565f | 2019-07-01 14:28:59 +0530 | [diff] [blame] | 38 | def handle_missed_call(**kwargs): |
Subin Tom | 8d30118 | 2022-02-23 12:59:38 +0530 | [diff] [blame] | 39 | status = "" |
Subin Tom | 5b79496 | 2022-02-25 16:52:25 +0530 | [diff] [blame] | 40 | call_type = kwargs.get("CallType") |
| 41 | dial_call_status = kwargs.get("DialCallStatus") |
Subin Tom | 8d30118 | 2022-02-23 12:59:38 +0530 | [diff] [blame] | 42 | |
Subin Tom | 5b79496 | 2022-02-25 16:52:25 +0530 | [diff] [blame] | 43 | if call_type == "incomplete" and dial_call_status == "no-answer": |
Ankush Menat | 7ef5480 | 2022-03-28 19:55:39 +0530 | [diff] [blame] | 44 | status = "No Answer" |
Subin Tom | 5b79496 | 2022-02-25 16:52:25 +0530 | [diff] [blame] | 45 | elif call_type == "client-hangup" and dial_call_status == "canceled": |
Ankush Menat | 7ef5480 | 2022-03-28 19:55:39 +0530 | [diff] [blame] | 46 | status = "Canceled" |
Subin Tom | 5b79496 | 2022-02-25 16:52:25 +0530 | [diff] [blame] | 47 | elif call_type == "incomplete" and dial_call_status == "failed": |
Ankush Menat | 7ef5480 | 2022-03-28 19:55:39 +0530 | [diff] [blame] | 48 | status = "Failed" |
Subin Tom | 8d30118 | 2022-02-23 12:59:38 +0530 | [diff] [blame] | 49 | |
| 50 | update_call_log(kwargs, status) |
Suraj Shetty | e9bfecf | 2019-06-03 12:27:02 +0530 | [diff] [blame] | 51 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 52 | |
| 53 | def update_call_log(call_payload, status="Ringing", call_log=None): |
Suraj Shetty | f5dd494 | 2019-07-16 11:07:25 +0530 | [diff] [blame] | 54 | call_log = call_log or get_call_log(call_payload) |
Subin Tom | 8d30118 | 2022-02-23 12:59:38 +0530 | [diff] [blame] | 55 | |
| 56 | # for a new sid, call_log and get_call_log will be empty so create a new log |
| 57 | if not call_log: |
| 58 | call_log = create_call_log(call_payload) |
Suraj Shetty | bd03a51 | 2019-05-27 15:30:41 +0530 | [diff] [blame] | 59 | if call_log: |
Suraj Shetty | c8c1742 | 2019-06-07 10:22:50 +0530 | [diff] [blame] | 60 | call_log.status = status |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 61 | call_log.to = call_payload.get("DialWhomNumber") |
| 62 | call_log.duration = call_payload.get("DialCallDuration") or 0 |
| 63 | call_log.recording_url = call_payload.get("RecordingUrl") |
Suraj Shetty | bd03a51 | 2019-05-27 15:30:41 +0530 | [diff] [blame] | 64 | call_log.save(ignore_permissions=True) |
| 65 | frappe.db.commit() |
Suraj Shetty | c8c1742 | 2019-06-07 10:22:50 +0530 | [diff] [blame] | 66 | return call_log |
Suraj Shetty | 863b93c | 2019-05-21 07:57:06 +0530 | [diff] [blame] | 67 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 68 | |
Suraj Shetty | 502565f | 2019-07-01 14:28:59 +0530 | [diff] [blame] | 69 | def get_call_log(call_payload): |
Suraj Shetty | 39abfae | 2022-04-04 07:28:41 +0530 | [diff] [blame] | 70 | call_log_id = call_payload.get("CallSid") |
| 71 | if frappe.db.exists("Call Log", call_log_id): |
| 72 | return frappe.get_doc("Call Log", call_log_id) |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 73 | |
Suraj Shetty | 1eeb89f | 2019-05-22 06:37:43 +0530 | [diff] [blame] | 74 | |
Sabu Siyad | 8e271fd | 2022-12-28 08:11:28 +0530 | [diff] [blame] | 75 | def map_custom_field(call_payload, call_log): |
| 76 | field_value = call_payload.get("CustomField") |
| 77 | |
| 78 | if not field_value: |
| 79 | return call_log |
| 80 | |
| 81 | settings = get_exotel_settings() |
| 82 | target_doctype = settings.target_doctype |
| 83 | mapping_enabled = settings.map_custom_field_to_doctype |
| 84 | |
| 85 | if not mapping_enabled or not target_doctype: |
| 86 | return call_log |
| 87 | |
| 88 | call_log.append("links", {"link_doctype": target_doctype, "link_name": field_value}) |
| 89 | |
| 90 | return call_log |
| 91 | |
| 92 | |
Suraj Shetty | 502565f | 2019-07-01 14:28:59 +0530 | [diff] [blame] | 93 | def create_call_log(call_payload): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 94 | call_log = frappe.new_doc("Call Log") |
| 95 | call_log.id = call_payload.get("CallSid") |
| 96 | call_log.to = call_payload.get("DialWhomNumber") |
| 97 | call_log.medium = call_payload.get("To") |
| 98 | call_log.status = "Ringing" |
| 99 | setattr(call_log, "from", call_payload.get("CallFrom")) |
Sabu Siyad | 8e271fd | 2022-12-28 08:11:28 +0530 | [diff] [blame] | 100 | map_custom_field(call_payload, call_log) |
Suraj Shetty | 502565f | 2019-07-01 14:28:59 +0530 | [diff] [blame] | 101 | call_log.save(ignore_permissions=True) |
| 102 | frappe.db.commit() |
| 103 | return call_log |
Suraj Shetty | 340ccb6 | 2019-06-17 10:16:38 +0530 | [diff] [blame] | 104 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 105 | |
Suraj Shetty | 07fe299 | 2019-05-22 15:48:57 +0530 | [diff] [blame] | 106 | @frappe.whitelist() |
Suraj Shetty | 1eeb89f | 2019-05-22 06:37:43 +0530 | [diff] [blame] | 107 | def get_call_status(call_id): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 108 | endpoint = get_exotel_endpoint("Calls/{call_id}.json".format(call_id=call_id)) |
Suraj Shetty | 06f8034 | 2019-06-13 17:13:54 +0530 | [diff] [blame] | 109 | response = requests.get(endpoint) |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 110 | status = response.json().get("Call", {}).get("Status") |
Suraj Shetty | 07fe299 | 2019-05-22 15:48:57 +0530 | [diff] [blame] | 111 | return status |
Suraj Shetty | 1eeb89f | 2019-05-22 06:37:43 +0530 | [diff] [blame] | 112 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 113 | |
Suraj Shetty | 07fe299 | 2019-05-22 15:48:57 +0530 | [diff] [blame] | 114 | @frappe.whitelist() |
Sabu Siyad | 8e271fd | 2022-12-28 08:11:28 +0530 | [diff] [blame] | 115 | def make_a_call(from_number, to_number, caller_id, **kwargs): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 116 | endpoint = get_exotel_endpoint("Calls/connect.json?details=true") |
| 117 | response = requests.post( |
Sabu Siyad | 8e271fd | 2022-12-28 08:11:28 +0530 | [diff] [blame] | 118 | endpoint, data={"From": from_number, "To": to_number, "CallerId": caller_id, **kwargs} |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 119 | ) |
Suraj Shetty | 1eeb89f | 2019-05-22 06:37:43 +0530 | [diff] [blame] | 120 | |
| 121 | return response.json() |
| 122 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 123 | |
Suraj Shetty | 1eeb89f | 2019-05-22 06:37:43 +0530 | [diff] [blame] | 124 | def get_exotel_settings(): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 125 | return frappe.get_single("Exotel Settings") |
| 126 | |
Suraj Shetty | e9bfecf | 2019-06-03 12:27:02 +0530 | [diff] [blame] | 127 | |
Suraj Shetty | e9bfecf | 2019-06-03 12:27:02 +0530 | [diff] [blame] | 128 | def whitelist_numbers(numbers, caller_id): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 129 | endpoint = get_exotel_endpoint("CustomerWhitelist") |
| 130 | response = requests.post( |
| 131 | endpoint, |
| 132 | data={ |
| 133 | "VirtualNumber": caller_id, |
| 134 | "Number": numbers, |
| 135 | }, |
| 136 | ) |
Suraj Shetty | e9bfecf | 2019-06-03 12:27:02 +0530 | [diff] [blame] | 137 | |
Suraj Shetty | 06f8034 | 2019-06-13 17:13:54 +0530 | [diff] [blame] | 138 | return response |
| 139 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 140 | |
Suraj Shetty | 06f8034 | 2019-06-13 17:13:54 +0530 | [diff] [blame] | 141 | def get_all_exophones(): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 142 | endpoint = get_exotel_endpoint("IncomingPhoneNumbers") |
Suraj Shetty | 06f8034 | 2019-06-13 17:13:54 +0530 | [diff] [blame] | 143 | response = requests.post(endpoint) |
| 144 | return response |
| 145 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 146 | |
Suraj Shetty | 06f8034 | 2019-06-13 17:13:54 +0530 | [diff] [blame] | 147 | def get_exotel_endpoint(action): |
| 148 | settings = get_exotel_settings() |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 149 | return "https://{api_key}:{api_token}@api.exotel.com/v1/Accounts/{sid}/{action}".format( |
| 150 | api_key=settings.api_key, api_token=settings.api_token, sid=settings.account_sid, action=action |
Suraj Shetty | af2eac4 | 2019-09-17 15:53:23 +0530 | [diff] [blame] | 151 | ) |