def do_render(self, request): request.setResponseCode(http.OK) request.setHeader('Content-Type', 'text/plain') try: message_id = '%s.%s' % (self.transport_name, request.args['messageid'][0]) yield self.publish_func( transport_name=self.transport_name, transport_type='sms', message_id=message_id, transport_metadata={ 'original_message_id': message_id, 'timestamp': iso8601(request.args['time'][0]), 'network_id': request.args['provider'][0], 'keyword': request.args['keyword'][0], }, to_addr=normalize_msisdn(request.args['destination'][0]), from_addr=normalize_msisdn(request.args['sender'][0]), content=request.args['text'][0], ) log.msg("Enqueued.") except KeyError, e: request.setResponseCode(http.BAD_REQUEST) msg = ("Need more request keys to complete this request. \n\n" "Missing request key: %s" % (e,)) log.msg('Returning %s: %s' % (http.BAD_REQUEST, msg)) request.write(msg)
def do_render(self, request): request.setResponseCode(http.OK) request.setHeader('Content-Type', 'text/plain') try: message_id = '%s.%s' % (self.transport_name, request.args['messageid'][0]) yield self.publish_func( transport_name=self.transport_name, transport_type='sms', message_id=message_id, transport_metadata={ 'original_message_id': message_id, 'timestamp': iso8601(request.args['time'][0]), 'network_id': request.args['provider'][0], 'keyword': request.args['keyword'][0], }, to_addr=normalize_msisdn(request.args['destination'][0]), from_addr=normalize_msisdn(request.args['sender'][0]), content=request.args['text'][0], ) log.msg("Enqueued.") except KeyError, e: request.setResponseCode(http.BAD_REQUEST) msg = "Need more request keys to complete this request. \n\n" \ "Missing request key: %s" % e log.msg('Returning %s: %s' % (http.BAD_REQUEST, msg)) request.write(msg)
def do_render(self, request): request.setResponseCode(http.OK) request.setHeader('Content-Type', 'text/plain') try: yield self.publisher.publish_message(TransportSMS( transport=self.transport_name, message_id=request.args['messageid'][0], transport_message_id=request.args['messageid'][0], transport_metadata={ 'timestamp': iso8601(request.args['time'][0]), 'network_id': request.args['provider'][0], 'keyword': request.args['keyword'][0], }, to_addr=normalize_msisdn(request.args['destination'][0]), from_addr=normalize_msisdn(request.args['sender'][0]), message=request.args['text'][0], ), routing_key='sms.inbound.%s.%s' % ( self.transport_name, request.args['destination'][0])) log.msg("Enqueued.") except KeyError, e: request.setResponseCode(http.BAD_REQUEST) msg = "Need more request keys to complete this request. \n\n" \ "Missing request key: %s" % e log.msg('Returning %s: %s' % (http.BAD_REQUEST, msg)) request.write(msg)
def render_POST(self, request): content = request.content.read() sms = utils.parse_post_event_xml(content) self.callback( to_addr=normalize_msisdn(sms['Local'], country_code='27'), from_addr=normalize_msisdn(sms['Remote'], country_code='27'), content=sms['Text'], transport_type='sms', message_id=sms['MessageID'], transport_metadata={ 'provider': sms['MobileNetwork'] }) request.setResponseCode(http.OK) request.setHeader('Content-Type', 'text/xml; charset=utf8') return content
def render_POST(self, request): content = get_receipts_xml(request.content.read()) sms = utils.parse_post_event_xml(content) self.callback(to_addr=normalize_msisdn(sms['Local'], country_code='27'), from_addr=normalize_msisdn(sms['Remote'], country_code='27'), content=sms['Text'], transport_type='sms', message_id=sms['MessageID'], transport_metadata={'provider': sms['MobileNetwork']}) request.setResponseCode(http.OK) request.setHeader('Content-Type', 'text/xml; charset=utf8') return content
def publish_inbound_message(self, message): self.publish_message( to_addr=normalize_msisdn(self.phone_number, country_code=self.country_code), from_addr=normalize_msisdn(str(message['Number']), country_code=self.country_code), content=message['Text'], transport_type='sms', message_id=uuid4().get_hex(), transport_metadata={ # when it was received on the modem 'received_at': message['DateTime'], # when it was retrieved from the modem 'read_at': message['SMSCDateTime'], })
def do_render(self, request): log.msg('got hit with %s' % request.args) request.setResponseCode(http.OK) request.setHeader('Content-Type', 'text/plain') try: message_id = '%s.%s' % (self.transport_name, request.args['messageid'][0]) status = int(request.args['status'][0]) delivery_status = 'pending' if status < 0: delivery_status = 'failed' elif status in [2, 14]: delivery_status = 'delivered' yield self.publish_func( user_message_id=message_id, delivery_status=delivery_status, transport_metadata={ 'delivery_status': request.args['status'][0], 'delivery_message': request.args['text'][0], 'timestamp': iso8601(request.args['time'][0]), 'network_id': request.args['provider'][0], }, to_addr=normalize_msisdn(request.args['sender'][0]), ) except KeyError, e: request.setResponseCode(http.BAD_REQUEST) msg = "Need more request keys to complete this request. \n\n" \ "Missing request key: %s" % e log.msg('Returning %s: %s' % (http.BAD_REQUEST, msg)) request.write(msg)
def handle_outbound(self, message, endpoint): to_addr = normalize_msisdn(message.get('to_addr'), country_code=self.country_code) if self.strip_plus: to_addr = to_addr.lstrip('+') message['to_addr'] = to_addr return message
def do_render(self, request): log.msg('got hit with %s' % request.args) request.setResponseCode(http.OK) request.setHeader('Content-Type', 'text/plain') try: message_id = '%s.%s' % (self.transport_name, request.args['messageid'][0]) status = int(request.args['status'][0]) delivery_status = 'pending' if status < 0: delivery_status = 'failed' elif status in [2, 14]: delivery_status = 'delivered' yield self.publish_func( user_message_id=message_id, delivery_status=delivery_status, transport_metadata={ 'delivery_status': request.args['status'][0], 'delivery_message': request.args['text'][0], 'timestamp': iso8601(request.args['time'][0]), 'network_id': request.args['provider'][0], }, to_addr=normalize_msisdn(request.args['sender'][0]), ) except KeyError, e: request.setResponseCode(http.BAD_REQUEST) msg = ("Need more request keys to complete this request. \n\n" "Missing request key: %s" % (e,)) log.msg('Returning %s: %s' % (http.BAD_REQUEST, msg)) request.write(msg)
def _handle_receive(self, message_id, request): if not self._check_request_args(request, ['secret', 'sent_timestamp', 'sent_to', 'from', 'message']): log.warning("Bad request: %r (args: %r)" % (request, request.args)) yield self._send_response(message_id, success=self.SMSSYNC_FALSE) return msginfo = yield self.msginfo_for_request(request) supplied_secret = request.args['secret'][0] if msginfo is None or (msginfo.smssync_secret and not msginfo.smssync_secret == supplied_secret): log.warning("Bad secret or account: %r (args: %r)" % (request, request.args)) yield self._send_response(message_id, success=self.SMSSYNC_FALSE) return timestamp = self._parse_timestamp(request) normalize = lambda raw: normalize_msisdn(raw, msginfo.country_code) message = { 'message_id': message_id, 'transport_type': self.transport_type, 'to_addr': normalize(request.args['sent_to'][0]), 'from_addr': normalize(request.args['from'][0]), 'content': request.args['message'][0], 'timestamp': timestamp, } self.add_msginfo_metadata(message, msginfo) yield self.publish_message(**message) self.callLater(self._reply_delay, self._respond_with_pending_messages, msginfo, message_id, success=self.SMSSYNC_TRUE)
def ussd_callback(self, msisdn, ussd_type, phase, message): log.msg("Received USSD, from: %s, message: %s" % (msisdn, message)) session_event = self.SSMI_TO_VUMI_EVENT[ussd_type] msisdn = normalize_msisdn(msisdn) message = message.decode(self.SSMI_ENCODING) if session_event == TransportUserMessage.SESSION_NEW: # If it's a new session then store the message as the USSD code ussd_code = message self.set_ussd_code(msisdn, ussd_code) text = None elif session_event == TransportUserMessage.SESSION_CLOSE: ussd_code = self.get_ussd_code(msisdn, delete=True) text = message elif session_event == TransportUserMessage.SESSION_RESUME: ussd_code = self.get_ussd_code(msisdn) text = message self.publish_message( from_addr=msisdn, to_addr=ussd_code, session_event=session_event, content=text, transport_name=self.transport_name, transport_type=self.transport_type, transport_metadata={}, )
def _handle_receive(self, message_id, request): if not self._check_request_args(request, ["secret", "sent_timestamp", "sent_to", "from", "message"]): log.warning("Bad request: %r (args: %r)" % (request, request.args)) yield self._send_response(message_id, success=self.SMSSYNC_FALSE) return msginfo = yield self.msginfo_for_request(request) supplied_secret = request.args["secret"][0] if msginfo is None or (msginfo.smssync_secret and not msginfo.smssync_secret == supplied_secret): log.warning("Bad secret or account: %r (args: %r)" % (request, request.args)) yield self._send_response(message_id, success=self.SMSSYNC_FALSE) return timestamp = self._parse_timestamp(request) normalize = lambda raw: normalize_msisdn(raw, msginfo.country_code) message = { "message_id": message_id, "transport_type": self.transport_type, "to_addr": normalize(request.args["sent_to"][0]), "from_addr": normalize(request.args["from"][0]), "content": request.args["message"][0], "timestamp": timestamp, } self.add_msginfo_metadata(message, msginfo) yield self.publish_message(**message) self.callLater( self._reply_delay, self._respond_with_pending_messages, msginfo, message_id, success=self.SMSSYNC_TRUE )
def normalize_address(address): """ Normalize a ParlayX address. """ if address.startswith('tel:'): address = address[4:] return normalize_msisdn(address)
def normalize_addr(self, addr): if self.normalize_config: addr = normalize_msisdn( addr, country_code=self.normalize_config["country_code"]) if self.normalize_config.get("strip_plus"): addr = addr.lstrip("+") return addr
def do_render(self, request): log.msg('got hit with %s' % request.args) try: request.setResponseCode(http.OK) request.setHeader('Content-Type', 'text/plain') status = int(request.args['status'][0]) delivery_status = 'pending' if status < 0: delivery_status = 'failed' elif status in [2, 14]: delivery_status = 'delivered' yield self.publisher.publish_message(TransportSMSDeliveryReport( transport=self.transport_name, message_id=request.args['messageid'][0], transport_message_id=request.args['smsid'][0], transport_metadata={ 'delivery_status': request.args['status'][0], 'delivery_message': request.args['text'][0], 'timestamp': iso8601(request.args['time'][0]), 'network_id': request.args['provider'][0], }, to_addr=normalize_msisdn(request.args['sender'][0]), delivery_status=delivery_status, ), routing_key='sms.receipt.%s' % (self.transport_name)) except KeyError, e: request.setResponseCode(http.BAD_REQUEST) msg = "Need more request keys to complete this request. \n\n" \ "Missing request key: %s" % e log.msg('Returning %s: %s' % (http.BAD_REQUEST, msg)) request.write(msg)
def normalize_msisdn_int(self, value): value = self.normalize_string(value) value = self.lchop(value, ['+', '00']) float_value = self.normalize_float(value) if not (self.is_numeric(value) and float_value.is_integer()): raise FieldNormalizerException('Invalid MSISDN: %s' % (value,)) msisdn = self.normalize_string(self.normalize_integer(float_value)) country_code = msisdn[:3] return self.normalize_string(normalize_msisdn(msisdn, country_code))
def test_normalize_msisdn(self): self.assertEqual(normalize_msisdn('0761234567', '27'), '+27761234567') self.assertEqual(normalize_msisdn('27761234567', '27'), '+27761234567') self.assertEqual(normalize_msisdn('+27761234567', '27'), '+27761234567') self.assertEqual(normalize_msisdn('0027761234567', '27'), '+27761234567') self.assertEqual(normalize_msisdn('1234'), '1234') self.assertEqual(normalize_msisdn('12345'), '12345') self.assertEqual(normalize_msisdn('+12345'), '+12345')
def clean_msisdn(self): """ Make a best effort guess at determining whether this msisdn is a valid msisdn """ if not self.cleaned_data['msisdn']: return '' msisdn = ''.join([char for char in self.cleaned_data['msisdn'] if char.isdigit()]) if len(msisdn) <= 5: raise forms.ValidationError('Please provide a valid phone number.') return normalize_msisdn(msisdn)
def render_POST(self, request): try: content = get_receipts_xml(request.content.read()) sms = utils.parse_post_event_xml(content) for field in [ 'Local', 'Remote', 'Text', 'MessageID', 'MobileNetwork']: if field not in sms: raise BadRequestError("Missing field: %s" % (field,)) except BadRequestError as err: request.setResponseCode(http.BAD_REQUEST) request.setHeader('Content-Type', 'text/plain; charset=utf8') return err.args[0] self.callback( to_addr=normalize_msisdn(sms['Local'], country_code='27'), from_addr=normalize_msisdn(sms['Remote'], country_code='27'), content=sms['Text'], transport_type='sms', message_id=sms['MessageID'], transport_metadata={ 'provider': sms['MobileNetwork'] }) request.setResponseCode(http.OK) request.setHeader('Content-Type', 'text/xml; charset=utf8') return content
def render_POST(self, request): try: content = get_receipts_xml(request.content.read()) sms = utils.parse_post_event_xml(content) for field in [ 'Local', 'Remote', 'Text', 'MessageID', 'MobileNetwork' ]: if field not in sms: raise BadRequestError("Missing field: %s" % (field, )) except BadRequestError as err: request.setResponseCode(http.BAD_REQUEST) request.setHeader('Content-Type', 'text/plain; charset=utf8') return err.args[0] self.callback(to_addr=normalize_msisdn(sms['Local'], country_code='27'), from_addr=normalize_msisdn(sms['Remote'], country_code='27'), content=sms['Text'], transport_type='sms', message_id=sms['MessageID'], transport_metadata={'provider': sms['MobileNetwork']}) request.setResponseCode(http.OK) request.setHeader('Content-Type', 'text/xml; charset=utf8') return content
def handle_raw_inbound_message(self, ussd_message): if ussd_message.command_name == 'EXTENDED_USSD_MESSAGE': genfields = { 'IMSI': '', 'Subscriber Type': '', 'OperatorID': '', 'SessionID': '', 'ValiPort': '', } genfield_values = ussd_message.genfields.split(':') genfields.update( dict(zip(genfields.keys(), genfield_values))) else: genfields = {} session_event = self.SSMI_TO_VUMI_EVENT[ussd_message.type] msisdn = normalize_msisdn(ussd_message.msisdn) message = ussd_message.message.decode(self.encoding) if session_event == TransportUserMessage.SESSION_NEW: # If it's a new session then store the message as the USSD code if not message.endswith('#'): message = '%s#' % (message,) session = yield self.session_manager.create_session( msisdn, ussd_code=message) text = None else: session = yield self.session_manager.load_session(msisdn) text = message if session_event == TransportUserMessage.SESSION_CLOSE: yield self.session_manager.clear_session(msisdn) yield self.publish_message( from_addr=msisdn, to_addr=session['ussd_code'], session_event=session_event, content=text, transport_type='ussd', transport_metadata={}, helper_metadata={ 'truteq': { 'genfields': genfields, } })
def render(self, request): request.setResponseCode(http.OK) request.setHeader('Content-Type', 'text/plain') hxg_msg = hxg.parse(request.content.read()) if hxg_msg.get('Type') != 'OnUSSEvent': # TODO: add support for non-USSD messages return '' text = hxg_msg.get('USSText', '').strip() if hxg_msg['EventType'] == 'Request': if text == 'REQ': # This indicates a new session event but Integrat # also sends a non-request message with type 'open' # below (and that is the one we use to trigger Vumi's # new session message. return '' else: session_event = TransportUserMessage.SESSION_RESUME else: event_type = hxg_msg['EventType'].lower() if event_type in self.EVENTS_TO_SKIP: return '' session_event = self.EVENT_TYPE_MAP.get(event_type, TransportUserMessage.SESSION_RESUME) if session_event != TransportUserMessage.SESSION_RESUME: text = None transport_metadata = { 'session_id': hxg_msg['SessionID'], } self.publish_message( from_addr=normalize_msisdn(hxg_msg['MSISDN']), to_addr=hxg_msg['ConnStr'], session_event=session_event, content=text, transport_name=self.transport_name, transport_type=self.transport_type, transport_metadata=transport_metadata, ) return ''
def game_key(self, msisdn): "Key for looking up a users game in data store.""" msisdn = normalize_msisdn(msisdn) userid = msisdn.lstrip('+') return "%s#%s" % (self.r_prefix, userid)
def test_unicode_addr_remains_unicode(self): addr = normalize_msisdn(u'0761234567', '27') self.assertEqual(addr, u'+27761234567') self.assertTrue(isinstance(addr, unicode))
def test_short_address(self): self.assertEqual(normalize_msisdn('1234'), '1234') self.assertEqual(normalize_msisdn('12345'), '12345')
def test_short_address_with_leading_plus(self): self.assertEqual(normalize_msisdn('+12345'), '+12345')
def test_no_leading_plus_or_zero(self): self.assertEqual(normalize_msisdn('27761234567', '27'), '+27761234567')
def test_double_leading_zero(self): self.assertEqual(normalize_msisdn('0027761234567', '27'), '+27761234567')
def handle_inbound(self, message, endpoint): from_addr = normalize_msisdn(message.get("from_addr"), country_code=self.country_code) message["from_addr"] = from_addr return message
def test_str_addr_remains_str(self): addr = normalize_msisdn('0761234567', '27') self.assertEqual(addr, '+27761234567') self.assertTrue(isinstance(addr, str))
def handle_inbound(self, message, endpoint): from_addr = normalize_msisdn(message.get('from_addr'), country_code=self.country_code) message['from_addr'] = from_addr return message
def handle_outbound(self, message, endpoint): to_addr = normalize_msisdn(message.get("to_addr"), country_code=self.country_code) if self.strip_plus: to_addr = to_addr.lstrip("+") message["to_addr"] = to_addr return message