def send(self, channel, msg, text): # url used for logs and exceptions url = 'https://api.plivo.com/v1/Account/%s/Message/' % channel.config[Channel.CONFIG_PLIVO_AUTH_ID] client = plivo.RestAPI(channel.config[Channel.CONFIG_PLIVO_AUTH_ID], channel.config[Channel.CONFIG_PLIVO_AUTH_TOKEN]) status_url = "https://" + settings.TEMBA_HOST + "%s" % reverse('handlers.plivo_handler', args=['status', channel.uuid]) payload = {'src': channel.address.lstrip('+'), 'dst': msg.urn_path.lstrip('+'), 'text': text, 'url': status_url, 'method': 'POST'} event = HttpEvent('POST', url, json.dumps(payload)) start = time.time() try: # TODO: Grab real request and response here plivo_response_status, plivo_response = client.send_message(params=payload) event.status_code = plivo_response_status event.response_body = plivo_response except Exception as e: # pragma: no cover raise SendException(six.text_type(e), event=event, start=start) if plivo_response_status != 200 and plivo_response_status != 201 and plivo_response_status != 202: raise SendException("Got non-200 response [%d] from API" % plivo_response_status, event=event, start=start) external_id = plivo_response['message_uuid'][0] Channel.success(channel, msg, WIRED, start, event=event, external_id=external_id)
def send_message_via_nexmo(self, from_number, to_number, text): from temba.channels.models import SendException params = dict(api_key=self.api_key, api_secret=self.api_secret) params['from'] = from_number.strip('+') params['to'] = to_number.strip('+') params['text'] = text params['status-report-req'] = 1 # if this isn't going to work as plaintext, send as unicode instead if not is_gsm7(text): params['type'] = 'unicode' log_params = params.copy() log_params['api_secret'] = 'x' * len(log_params['api_secret']) log_url = NexmoClient.SEND_URL + '?' + urlencode(log_params) event = HttpEvent('GET', log_url) try: response = requests.get(NexmoClient.SEND_URL, params=params) event.status_code = response.status_code event.response_body = response.text response_json = response.json() messages = response_json.get('messages', []) except Exception: raise SendException(u"Failed sending message: %s" % response.text, event=event) if not messages or int(messages[0]['status']) != 0: raise SendException(u"Failed sending message, received error status [%s]" % messages[0]['status'], event=event) else: return messages[0]['message-id'], event
def send_whatsapp(self, channel_struct, msg, payload, attachments=None): url = ('%s/messages/' % (self.wassup_url(), )) headers = self.api_request_headers(channel_struct) event = HttpEvent('POST', url, json.dumps(payload)) start = time.time() # Grab the first attachment if it exists attachments = Attachment.parse_all(msg.attachments) attachment = attachments[0] if attachments else None try: if attachment: files = self.fetch_attachment(attachment) data = payload else: headers.update({'Content-Type': 'application/json'}) data = json.dumps(payload) files = {} response = requests.post(url, data=data, files=files, headers=headers) response.raise_for_status() event.status_code = response.status_code event.response_body = response.text except (requests.RequestException, ) as e: raise SendException( 'error: %s, request: %r, response: %r' % (six.text_type(e), e.request.body, e.response.content), event=event, start=start) data = response.json() try: message_id = data['uuid'] Channel.success(channel_struct, msg, WIRED, start, event=event, external_id=message_id) except (KeyError, ) as e: raise SendException( "Unable to read external message_id: %r" % (e, ), event=HttpEvent('POST', url, request_body=json.dumps(json.dumps(payload)), response_body=json.dumps(data)), start=start)
def send_message(self, from_number, to_number, text): from temba.channels.models import SendException params = dict(api_key=self.api_key, api_secret=self.api_secret) params['from'] = from_number.strip('+') params['to'] = to_number.strip('+') params['text'] = text params['status-report-req'] = 1 # if this isn't going to work as plaintext, send as unicode instead if not is_gsm7(text): params['type'] = 'unicode' response = requests.get(NexmoClient.SEND_URL, params=params) response_json = response.json() messages = response_json.get('messages', []) if not messages or int(messages[0]['status']) != 0: raise SendException( u"Failed sending message, received error status [%s]" % messages[0]['status'], method=response.request.method, url=response.request.url, request=None, response=response.text, response_status=response.status_code) else: return (messages[0]['message-id'], response)
def send(self, channel, msg, text): auth_id = channel.config[Channel.CONFIG_PLIVO_AUTH_ID] auth_token = channel.config[Channel.CONFIG_PLIVO_AUTH_TOKEN] url = 'https://api.plivo.com/v1/Account/%s/Message/' % auth_id status_url = "https://%s%s" % (channel.callback_domain, reverse('handlers.plivo_handler', args=['status', channel.uuid])) payload = { 'src': channel.address.lstrip('+'), 'dst': msg.urn_path.lstrip('+'), 'text': text, 'url': status_url, 'method': 'POST' } event = HttpEvent('POST', url, json.dumps(payload)) headers = http_headers(extra={'Content-Type': "application/json"}) start = time.time() try: # TODO: Grab real request and response here response = requests.post(url, json=payload, headers=headers, auth=(auth_id, auth_token)) event.status_code = response.status_code event.response_body = response.json() except Exception as e: # pragma: no cover raise SendException(six.text_type(e), event=event, start=start) if response.status_code not in [200, 201, 202]: # pragma: no cover raise SendException("Got non-200 response [%d] from API" % response.status_code, event=event, start=start) external_id = response.json()['message_uuid'][0] Channel.success(channel, msg, WIRED, start, event=event, external_id=external_id)
def send_message(self, data, start): from temba.channels.models import SendException access_token = self.get_access_token() url = 'https://channels.jiochat.com/custom/custom_send.action' event = HttpEvent('POST', url, json.dumps(data)) try: response = self._request(url, 'POST_JSON', data, access_token) event.status_code = response.status_code event.response_body = response.text except Exception as e: raise SendException(six.text_type(e), event=event, start=start) if response.status_code != 200 and response.status_code != 201 and response.status_code != 202: raise SendException("Got non-200 response [%d] from JioChat" % response.status_code, event=event, start=start) return response, event
def send(self, channel, msg, text): connection = None # if the channel config has specified and override hostname use that, otherwise use settings event_hostname = channel.config.get(Channel.CONFIG_RP_HOSTNAME_OVERRIDE, settings.HOSTNAME) # the event url Junebug will relay events to event_url = 'http://%s%s' % (event_hostname, reverse('courier.jn', args=[channel.uuid, 'event'])) is_ussd = Channel.get_type_from_code(channel.channel_type).category == ChannelType.Category.USSD # build our payload payload = {'event_url': event_url, 'content': text} if channel.secret is not None: payload['event_auth_token'] = channel.secret if is_ussd: connection = USSDSession.objects.get_with_status_only(msg.connection_id) # make sure USSD responses are only valid for a short window response_expiration = timezone.now() - timedelta(seconds=180) external_id = None if msg.response_to_id and msg.created_on > response_expiration: external_id = Msg.objects.values_list('external_id', flat=True).filter(pk=msg.response_to_id).first() # NOTE: Only one of `to` or `reply_to` may be specified, use external_id if we have it. if external_id: payload['reply_to'] = external_id else: payload['to'] = msg.urn_path payload['channel_data'] = { 'continue_session': connection and not connection.should_end or False, } else: payload['from'] = channel.address payload['to'] = msg.urn_path log_url = channel.config[Channel.CONFIG_SEND_URL] start = time.time() event = HttpEvent('POST', log_url, json.dumps(payload)) headers = {'Content-Type': 'application/json'} headers.update(TEMBA_HEADERS) try: response = requests.post( channel.config[Channel.CONFIG_SEND_URL], verify=True, json=payload, timeout=15, headers=headers, auth=(channel.config[Channel.CONFIG_USERNAME], channel.config[Channel.CONFIG_PASSWORD])) event.status_code = response.status_code event.response_body = response.text except Exception as e: raise SendException(unicode(e), event=event, start=start) if not (200 <= response.status_code < 300): raise SendException("Received a non 200 response %d from Junebug" % response.status_code, event=event, start=start) data = response.json() if is_ussd and connection and connection.should_end: connection.close() try: message_id = data['result']['message_id'] Channel.success(channel, msg, WIRED, start, event=event, external_id=message_id) except KeyError, e: raise SendException("Unable to read external message_id: %r" % (e,), event=HttpEvent('POST', log_url, request_body=json.dumps(json.dumps(payload)), response_body=json.dumps(data)), start=start)
def send(self, channel, msg, text): connection = None # if the channel config has specified and override hostname use that, otherwise use settings callback_domain = channel.config.get( Channel.CONFIG_RP_HOSTNAME_OVERRIDE, None) if not callback_domain: callback_domain = channel.callback_domain # the event url Junebug will relay events to event_url = "http://%s%s" % ( callback_domain, reverse("handlers.junebug_handler", args=["event", channel.uuid]), ) is_ussd = Channel.get_type_from_code( channel.channel_type).category == ChannelType.Category.USSD # build our payload payload = {"event_url": event_url, "content": text} secret = channel.config.get(Channel.CONFIG_SECRET) if secret is not None: payload["event_auth_token"] = secret connection = USSDSession.objects.get_with_status_only( msg.connection_id) # make sure USSD responses are only valid for a short window response_expiration = timezone.now() - timedelta(seconds=180) external_id = None if msg.response_to_id and msg.created_on > response_expiration: external_id = Msg.objects.values_list( "external_id", flat=True).filter(pk=msg.response_to_id).first() # NOTE: Only one of `to` or `reply_to` may be specified, use external_id if we have it. if external_id: payload["reply_to"] = external_id else: payload["to"] = msg.urn_path payload["channel_data"] = { "continue_session": connection and not connection.should_end or False } log_url = channel.config[Channel.CONFIG_SEND_URL] start = time.time() event = HttpEvent("POST", log_url, json.dumps(payload)) headers = http_headers(extra={"Content-Type": "application/json"}) try: response = requests.post( channel.config[Channel.CONFIG_SEND_URL], verify=True, json=payload, timeout=15, headers=headers, auth=(channel.config[Channel.CONFIG_USERNAME], channel.config[Channel.CONFIG_PASSWORD]), ) event.status_code = response.status_code event.response_body = response.text except Exception as e: raise SendException(str(e), event=event, start=start) if not (200 <= response.status_code < 300): raise SendException("Received a non 200 response %d from Junebug" % response.status_code, event=event, start=start) data = response.json() if is_ussd and connection and connection.should_end: connection.close() try: message_id = data["result"]["message_id"] Channel.success(channel, msg, WIRED, start, event=event, external_id=message_id) except KeyError as e: raise SendException( "Unable to read external message_id: %r" % (e, ), event=HttpEvent("POST", log_url, request_body=json.dumps(json.dumps(payload)), response_body=json.dumps(data)), start=start, )
def send(self, channel, msg, text): is_ussd = Channel.get_type_from_code( channel.channel_type).category == ChannelType.Category.USSD channel.config[ 'transport_name'] = 'ussd_transport' if is_ussd else 'mtech_ng_smpp_transport' session = None session_event = None in_reply_to = None if is_ussd: session = USSDSession.objects.get_with_status_only( msg.connection_id) if session and session.should_end: session_event = "close" else: session_event = "resume" if msg.response_to_id: in_reply_to = Msg.objects.values_list( 'external_id', flat=True).filter(pk=msg.response_to_id).first() payload = dict(message_id=msg.id, in_reply_to=in_reply_to, session_event=session_event, to_addr=msg.urn_path, from_addr=channel.address, content=text, transport_name=channel.config['transport_name'], transport_type='ussd' if is_ussd else 'sms', transport_metadata={}, helper_metadata={}) payload = json.dumps(payload) headers = http_headers(extra={'Content-Type': 'application/json'}) api_url_base = channel.config.get('api_url', Channel.VUMI_GO_API_URL) url = "%s/%s/messages.json" % (api_url_base, channel.config['conversation_key']) event = HttpEvent('PUT', url, json.dumps(payload)) start = time.time() validator = URLValidator() validator(url) try: response = requests.put(url, data=payload, headers=headers, timeout=30, auth=(channel.config['account_key'], channel.config['access_token'])) event.status_code = response.status_code event.response_body = response.text except Exception as e: raise SendException(six.text_type(e), event=event, start=start) if response.status_code not in (200, 201): # this is a fatal failure, don't retry fatal = response.status_code == 400 # if this is fatal due to the user opting out, stop them if response.text and response.text.find('has opted out') >= 0: contact = Contact.objects.get(id=msg.contact) contact.stop(contact.modified_by) fatal = True raise SendException("Got non-200 response [%d] from API" % response.status_code, event=event, fatal=fatal, start=start) # parse our response body = response.json() external_id = body.get('message_id', '') if is_ussd and session and session.should_end: session.close() Channel.success(channel, msg, WIRED, start, event=event, external_id=external_id)