| import frappe |
| import requests |
| from frappe import _ |
| |
| # api/method/erpnext.erpnext_integrations.exotel_integration.handle_incoming_call |
| # api/method/erpnext.erpnext_integrations.exotel_integration.handle_end_call |
| # api/method/erpnext.erpnext_integrations.exotel_integration.handle_missed_call |
| |
| |
| @frappe.whitelist(allow_guest=True) |
| def handle_incoming_call(**kwargs): |
| try: |
| exotel_settings = get_exotel_settings() |
| if not exotel_settings.enabled: |
| return |
| |
| call_payload = kwargs |
| status = call_payload.get("Status") |
| if status == "free": |
| return |
| |
| call_log = get_call_log(call_payload) |
| if not call_log: |
| create_call_log(call_payload) |
| else: |
| update_call_log(call_payload, call_log=call_log) |
| except Exception as e: |
| frappe.db.rollback() |
| frappe.log_error(title=_("Error in Exotel incoming call")) |
| frappe.db.commit() |
| |
| |
| @frappe.whitelist(allow_guest=True) |
| def handle_end_call(**kwargs): |
| update_call_log(kwargs, "Completed") |
| |
| |
| @frappe.whitelist(allow_guest=True) |
| def handle_missed_call(**kwargs): |
| update_call_log(kwargs, "Missed") |
| |
| |
| def update_call_log(call_payload, status="Ringing", call_log=None): |
| call_log = call_log or get_call_log(call_payload) |
| if call_log: |
| call_log.status = status |
| call_log.to = call_payload.get("DialWhomNumber") |
| call_log.duration = call_payload.get("DialCallDuration") or 0 |
| call_log.recording_url = call_payload.get("RecordingUrl") |
| call_log.save(ignore_permissions=True) |
| frappe.db.commit() |
| return call_log |
| |
| |
| def get_call_log(call_payload): |
| call_log = frappe.get_all( |
| "Call Log", |
| { |
| "id": call_payload.get("CallSid"), |
| }, |
| limit=1, |
| ) |
| |
| if call_log: |
| return frappe.get_doc("Call Log", call_log[0].name) |
| |
| |
| def create_call_log(call_payload): |
| call_log = frappe.new_doc("Call Log") |
| call_log.id = call_payload.get("CallSid") |
| call_log.to = call_payload.get("DialWhomNumber") |
| call_log.medium = call_payload.get("To") |
| call_log.status = "Ringing" |
| setattr(call_log, "from", call_payload.get("CallFrom")) |
| call_log.save(ignore_permissions=True) |
| frappe.db.commit() |
| return call_log |
| |
| |
| @frappe.whitelist() |
| def get_call_status(call_id): |
| endpoint = get_exotel_endpoint("Calls/{call_id}.json".format(call_id=call_id)) |
| response = requests.get(endpoint) |
| status = response.json().get("Call", {}).get("Status") |
| return status |
| |
| |
| @frappe.whitelist() |
| def make_a_call(from_number, to_number, caller_id): |
| endpoint = get_exotel_endpoint("Calls/connect.json?details=true") |
| response = requests.post( |
| endpoint, data={"From": from_number, "To": to_number, "CallerId": caller_id} |
| ) |
| |
| return response.json() |
| |
| |
| def get_exotel_settings(): |
| return frappe.get_single("Exotel Settings") |
| |
| |
| def whitelist_numbers(numbers, caller_id): |
| endpoint = get_exotel_endpoint("CustomerWhitelist") |
| response = requests.post( |
| endpoint, |
| data={ |
| "VirtualNumber": caller_id, |
| "Number": numbers, |
| }, |
| ) |
| |
| return response |
| |
| |
| def get_all_exophones(): |
| endpoint = get_exotel_endpoint("IncomingPhoneNumbers") |
| response = requests.post(endpoint) |
| return response |
| |
| |
| def get_exotel_endpoint(action): |
| settings = get_exotel_settings() |
| return "https://{api_key}:{api_token}@api.exotel.com/v1/Accounts/{sid}/{action}".format( |
| api_key=settings.api_key, api_token=settings.api_token, sid=settings.account_sid, action=action |
| ) |