class DeliverShortMessageProcessor(default.DeliverShortMessageProcessor): CONFIG_CLASS = DeliverShortMessageProcessorConfig def __init__(self, transport, config): super(DeliverShortMessageProcessor, self).__init__(transport, config) self.transport = transport self.redis = transport.redis self.config = self.CONFIG_CLASS(config, static=True) self.session_manager = SessionManager( self.redis, max_session_length=self.config.max_session_length) @inlineCallbacks def handle_deliver_sm_ussd(self, pdu, pdu_params, pdu_opts): service_op = pdu_opts['ussd_service_op'] mica_session_identifier = pdu_opts['user_message_reference'] vumi_session_identifier = make_vumi_session_identifier( pdu_params['source_addr'], mica_session_identifier) session_event = 'close' if service_op == '01': # PSSR request. Let's assume it means a new session. session_event = 'new' ussd_code = pdu_params['short_message'] content = None yield self.session_manager.create_session(vumi_session_identifier, ussd_code=ussd_code) elif service_op == '17': # PSSR response. This means session end. session_event = 'close' session = yield self.session_manager.load_session( vumi_session_identifier) ussd_code = session['ussd_code'] content = None yield self.session_manager.clear_session(vumi_session_identifier) else: session_event = 'continue' session = yield self.session_manager.load_session( vumi_session_identifier) ussd_code = session['ussd_code'] content = pdu_params['short_message'] # This is stashed on the message and available when replying # with a `submit_sm` session_info = { 'session_identifier': mica_session_identifier, } decoded_msg = self.dcs_decode(content, pdu_params['data_coding']) result = yield self.handle_short_message_content( source_addr=pdu_params['source_addr'], destination_addr=ussd_code, short_message=decoded_msg, message_type='ussd', session_event=session_event, session_info=session_info) returnValue(result)
class SubmitShortMessageProcessor(default.SubmitShortMessageProcessor): CONFIG_CLASS = SubmitShortMessageProcessorConfig def __init__(self, transport, config): super(SubmitShortMessageProcessor, self).__init__(transport, config) self.transport = transport self.redis = transport.redis self.config = self.CONFIG_CLASS(config, static=True) self.session_manager = SessionManager( self.redis, max_session_length=self.config.max_session_length) @inlineCallbacks def handle_outbound_message(self, message, protocol): to_addr = message['to_addr'] from_addr = message['from_addr'] text = message['content'] vumi_message_id = message['message_id'] session_event = message['session_event'] transport_type = message['transport_type'] optional_parameters = {} if transport_type == 'ussd': continue_session = (session_event != TransportUserMessage.SESSION_CLOSE) session_info = message['transport_metadata'].get( 'session_info', {}) mica_session_identifier = session_info.get('session_identifier', '') vumi_session_identifier = make_vumi_session_identifier( to_addr, mica_session_identifier) optional_parameters.update({ 'ussd_service_op': ('02' if continue_session else '17'), 'user_message_reference': (str(mica_session_identifier).zfill(2)), }) if not continue_session: yield self.session_manager.clear_session( vumi_session_identifier) if self.config.send_long_messages: resp = yield protocol.submit_sm_long( vumi_message_id, to_addr.encode('ascii'), long_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) elif self.config.send_multipart_sar: resp = yield protocol.submit_csm_sar( vumi_message_id, to_addr.encode('ascii'), short_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) elif self.config.send_multipart_udh: resp = yield protocol.submit_csm_udh( vumi_message_id, to_addr.encode('ascii'), short_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) else: resp = yield protocol.submit_sm( vumi_message_id, to_addr.encode('ascii'), short_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) returnValue(resp)
class SubmitShortMessageProcessor(default.SubmitShortMessageProcessor): CONFIG_CLASS = SubmitShortMessageProcessorConfig # NOTE: these values are hexidecimal because of python-smpp encoding # quirkiness ussd_service_op_map = { 'continue': '02', 'close': '17', # end } def __init__(self, transport, config): super(SubmitShortMessageProcessor, self).__init__(transport, config) self.transport = transport self.redis = transport.redis self.config = self.CONFIG_CLASS(config, static=True) self.session_manager = SessionManager( self.redis, max_session_length=self.config.max_session_length) @inlineCallbacks def handle_outbound_message(self, message, service): to_addr = message['to_addr'] from_addr = message['from_addr'] text = message['content'] if text is None: text = u"" vumi_message_id = message['message_id'] session_event = message['session_event'] transport_type = message['transport_type'] optional_parameters = {} if transport_type == 'ussd': continue_session = ( session_event != TransportUserMessage.SESSION_CLOSE) session_info = message['transport_metadata'].get( 'session_info', {}) mica_session_identifier = session_info.get( 'session_identifier', '') vumi_session_identifier = make_vumi_session_identifier( to_addr, mica_session_identifier) service_op = self.ussd_service_op_map[('continue' if continue_session else 'close')] optional_parameters.update({ 'ussd_service_op': service_op, 'user_message_reference': ( str(mica_session_identifier).zfill(2)), }) if not continue_session: yield self.session_manager.clear_session( vumi_session_identifier) resp = yield self.send_short_message( service, vumi_message_id, to_addr.encode('ascii'), text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters) returnValue(resp)
class DeliverShortMessageProcessor(default.DeliverShortMessageProcessor): CONFIG_CLASS = DeliverShortMessageProcessorConfig # NOTE: these keys are hexidecimal because of python-smpp encoding # quirkiness ussd_service_op_map = { '01': 'new', '12': 'continue', '81': 'close', # user abort } def __init__(self, transport, config): super(DeliverShortMessageProcessor, self).__init__(transport, config) self.transport = transport self.log = transport.log self.redis = transport.redis self.config = self.CONFIG_CLASS(config, static=True) self.session_manager = SessionManager( self.redis, max_session_length=self.config.max_session_length) @inlineCallbacks def handle_deliver_sm_ussd(self, pdu, pdu_params, pdu_opts): service_op = pdu_opts['ussd_service_op'] mica_session_identifier = pdu_opts['user_message_reference'] vumi_session_identifier = make_vumi_session_identifier( pdu_params['source_addr'], mica_session_identifier) session_event = self.ussd_service_op_map.get(service_op) if session_event == 'new': # PSSR request. Let's assume it means a new session. ussd_code = pdu_params['short_message'] content = None yield self.session_manager.create_session( vumi_session_identifier, ussd_code=ussd_code) elif session_event == 'close': session = yield self.session_manager.load_session( vumi_session_identifier) ussd_code = session['ussd_code'] content = None yield self.session_manager.clear_session(vumi_session_identifier) else: if session_event != 'continue': self.log.warning(( 'Received unknown %r ussd_service_op, assuming continue.') % (service_op,)) session_event = 'continue' session = yield self.session_manager.load_session( vumi_session_identifier) ussd_code = session['ussd_code'] content = self.dcs_decode( pdu_params['short_message'], pdu_params['data_coding']) # This is stashed on the message and available when replying # with a `submit_sm` session_info = { 'ussd_service_op': service_op, 'session_identifier': mica_session_identifier, } result = yield self.handle_short_message_content( source_addr=pdu_params['source_addr'], destination_addr=ussd_code, short_message=content, message_type='ussd', session_event=session_event, session_info=session_info) returnValue(result)
class SubmitShortMessageProcessor(default.SubmitShortMessageProcessor): CONFIG_CLASS = SubmitShortMessageProcessorConfig # NOTE: these values are hexidecimal because of python-smpp encoding # quirkiness ussd_service_op_map = { 'continue': '02', 'close': '17', # end } def __init__(self, transport, config): super(SubmitShortMessageProcessor, self).__init__(transport, config) self.transport = transport self.redis = transport.redis self.config = self.CONFIG_CLASS(config, static=True) self.session_manager = SessionManager( self.redis, max_session_length=self.config.max_session_length) @inlineCallbacks def handle_outbound_message(self, message, protocol): to_addr = message['to_addr'] from_addr = message['from_addr'] text = message['content'] if text is None: text = u"" vumi_message_id = message['message_id'] session_event = message['session_event'] transport_type = message['transport_type'] optional_parameters = {} if transport_type == 'ussd': continue_session = (session_event != TransportUserMessage.SESSION_CLOSE) session_info = message['transport_metadata'].get( 'session_info', {}) sixdee_session_identifier = session_info.get( 'session_identifier', '') vumi_session_identifier = make_vumi_session_identifier( to_addr, sixdee_session_identifier) its_session_info = (int(sixdee_session_identifier, 16) | int(not continue_session)) service_op = self.ussd_service_op_map[( 'continue' if continue_session else 'close')] optional_parameters.update({ 'ussd_service_op': service_op, 'its_session_info': "%04x" % (its_session_info, ) }) if not continue_session: yield self.session_manager.clear_session( vumi_session_identifier) if self.config.send_long_messages: resp = yield protocol.submit_sm_long( vumi_message_id, to_addr.encode('ascii'), long_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) elif self.config.send_multipart_sar: resp = yield protocol.submit_csm_sar( vumi_message_id, to_addr.encode('ascii'), short_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) elif self.config.send_multipart_udh: resp = yield protocol.submit_csm_udh( vumi_message_id, to_addr.encode('ascii'), short_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) else: resp = yield protocol.submit_sm( vumi_message_id, to_addr.encode('ascii'), short_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) returnValue(resp)
class DeliverShortMessageProcessor(default.DeliverShortMessageProcessor): CONFIG_CLASS = DeliverShortMessageProcessorConfig # NOTE: these keys are hexidecimal because of python-smpp encoding # quirkiness ussd_service_op_map = { '01': 'new', '12': 'continue', '81': 'close', # user abort } def __init__(self, transport, config): super(DeliverShortMessageProcessor, self).__init__(transport, config) self.transport = transport self.redis = transport.redis self.config = self.CONFIG_CLASS(config, static=True) self.session_manager = SessionManager( self.redis, max_session_length=self.config.max_session_length) @inlineCallbacks def handle_deliver_sm_ussd(self, pdu, pdu_params, pdu_opts): service_op = pdu_opts['ussd_service_op'] # 6D uses its_session_info as follows: # # * First 15 bit: dialog id (i.e. session id) # * Last bit: end session (1 to end, 0 to continue) its_session_number = int(pdu_opts['its_session_info'], 16) end_session = bool(its_session_number % 2) sixdee_session_identifier = "%04x" % (its_session_number & 0xfffe) vumi_session_identifier = make_vumi_session_identifier( pdu_params['source_addr'], sixdee_session_identifier) if end_session: session_event = 'close' else: session_event = self.ussd_service_op_map.get(service_op) if session_event == 'new': # PSSR request. Let's assume it means a new session. ussd_code = pdu_params['short_message'] content = None yield self.session_manager.create_session(vumi_session_identifier, ussd_code=ussd_code) elif session_event == 'close': session = yield self.session_manager.load_session( vumi_session_identifier) ussd_code = session['ussd_code'] content = None yield self.session_manager.clear_session(vumi_session_identifier) else: if session_event != 'continue': log.warning(('Received unknown %r ussd_service_op, ' 'assuming continue.') % (service_op, )) session_event = 'continue' session = yield self.session_manager.load_session( vumi_session_identifier) ussd_code = session['ussd_code'] content = pdu_params['short_message'] # This is stashed on the message and available when replying # with a `submit_sm` session_info = { 'ussd_service_op': service_op, 'session_identifier': sixdee_session_identifier, } decoded_msg = self.dcs_decode(content, pdu_params['data_coding']) result = yield self.handle_short_message_content( source_addr=pdu_params['source_addr'], destination_addr=ussd_code, short_message=decoded_msg, message_type='ussd', session_event=session_event, session_info=session_info) returnValue(result)
class SubmitShortMessageProcessor(default.SubmitShortMessageProcessor): CONFIG_CLASS = SubmitShortMessageProcessorConfig # NOTE: these values are hexidecimal because of python-smpp encoding # quirkiness ussd_service_op_map = { 'continue': '02', 'close': '17', # end } def __init__(self, transport, config): super(SubmitShortMessageProcessor, self).__init__(transport, config) self.transport = transport self.redis = transport.redis self.config = self.CONFIG_CLASS(config, static=True) self.session_manager = SessionManager( self.redis, max_session_length=self.config.max_session_length) @inlineCallbacks def handle_outbound_message(self, message, protocol): to_addr = message['to_addr'] from_addr = message['from_addr'] text = message['content'] if text is None: text = u"" vumi_message_id = message['message_id'] session_event = message['session_event'] transport_type = message['transport_type'] optional_parameters = {} if transport_type == 'ussd': continue_session = ( session_event != TransportUserMessage.SESSION_CLOSE) session_info = message['transport_metadata'].get( 'session_info', {}) sixdee_session_identifier = session_info.get( 'session_identifier', '') vumi_session_identifier = make_vumi_session_identifier( to_addr, sixdee_session_identifier) its_session_info = ( int(sixdee_session_identifier, 16) | int(not continue_session)) service_op = self.ussd_service_op_map[('continue' if continue_session else 'close')] optional_parameters.update({ 'ussd_service_op': service_op, 'its_session_info': "%04x" % (its_session_info,) }) if not continue_session: yield self.session_manager.clear_session( vumi_session_identifier) if self.config.send_long_messages: resp = yield protocol.submit_sm_long( vumi_message_id, to_addr.encode('ascii'), long_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) elif self.config.send_multipart_sar: resp = yield protocol.submit_csm_sar( vumi_message_id, to_addr.encode('ascii'), short_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) elif self.config.send_multipart_udh: resp = yield protocol.submit_csm_udh( vumi_message_id, to_addr.encode('ascii'), short_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) else: resp = yield protocol.submit_sm( vumi_message_id, to_addr.encode('ascii'), short_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) returnValue(resp)
class DeliverShortMessageProcessor(default.DeliverShortMessageProcessor): CONFIG_CLASS = DeliverShortMessageProcessorConfig # NOTE: these keys are hexidecimal because of python-smpp encoding # quirkiness ussd_service_op_map = { '01': 'new', '12': 'continue', '81': 'close', # user abort } def __init__(self, transport, config): super(DeliverShortMessageProcessor, self).__init__(transport, config) self.transport = transport self.redis = transport.redis self.config = self.CONFIG_CLASS(config, static=True) self.session_manager = SessionManager( self.redis, max_session_length=self.config.max_session_length) @inlineCallbacks def handle_deliver_sm_ussd(self, pdu, pdu_params, pdu_opts): service_op = pdu_opts['ussd_service_op'] # 6D uses its_session_info as follows: # # * First 15 bit: dialog id (i.e. session id) # * Last bit: end session (1 to end, 0 to continue) its_session_number = int(pdu_opts['its_session_info'], 16) end_session = bool(its_session_number % 2) sixdee_session_identifier = "%04x" % (its_session_number & 0xfffe) vumi_session_identifier = make_vumi_session_identifier( pdu_params['source_addr'], sixdee_session_identifier) if end_session: session_event = 'close' else: session_event = self.ussd_service_op_map.get(service_op) if session_event == 'new': # PSSR request. Let's assume it means a new session. ussd_code = pdu_params['short_message'] content = None yield self.session_manager.create_session( vumi_session_identifier, ussd_code=ussd_code) elif session_event == 'close': session = yield self.session_manager.load_session( vumi_session_identifier) ussd_code = session['ussd_code'] content = None yield self.session_manager.clear_session(vumi_session_identifier) else: if session_event != 'continue': log.warning(('Received unknown %r ussd_service_op, ' 'assuming continue.') % (service_op,)) session_event = 'continue' session = yield self.session_manager.load_session( vumi_session_identifier) ussd_code = session['ussd_code'] content = pdu_params['short_message'] # This is stashed on the message and available when replying # with a `submit_sm` session_info = { 'ussd_service_op': service_op, 'session_identifier': sixdee_session_identifier, } decoded_msg = self.dcs_decode(content, pdu_params['data_coding']) result = yield self.handle_short_message_content( source_addr=pdu_params['source_addr'], destination_addr=ussd_code, short_message=decoded_msg, message_type='ussd', session_event=session_event, session_info=session_info) returnValue(result)
class TwilioAPIWorker(ApplicationWorker): """Emulates the Twilio API to use vumi as if it was Twilio""" CONFIG_CLASS = TwilioAPIConfig @inlineCallbacks def setup_application(self): """Application specific setup""" self.app_config = self.get_static_config() self.server = TwilioAPIServer(self, self.app_config.api_version) path = os.path.join( self.app_config.web_path, self.app_config.api_version) self.webserver = self.start_web_resources([ (self.server.app.resource(), path)], self.app_config.web_port) redis = yield TxRedisManager.from_config(self.app_config.redis_manager) self.session_manager = SessionManager( redis, self.app_config.redis_timeout) self.session_lookup = SessionIDLookup( redis, self.app_config.redis_timeout, self.app_config.session_lookup_namespace) @inlineCallbacks def teardown_application(self): """Clean-up of setup done in `setup_application`""" yield self.webserver.loseConnection() yield self.session_manager.stop() def _http_request(self, url='', method='GET', data={}): return treq.request(method, url, persistent=False, data=data) def _request_data_from_session(self, session): return { 'CallSid': session['CallId'], 'AccountSid': session['AccountSid'], 'From': session['From'], 'To': session['To'], 'CallStatus': session['Status'], 'ApiVersion': self.app_config.api_version, 'Direction': session['Direction'], } @inlineCallbacks def _get_twiml_from_client(self, session, data=None): if data is None: data = self._request_data_from_session(session) twiml_raw = yield self._http_request( session['Url'], session['Method'], data) if twiml_raw.code < 200 or twiml_raw.code >= 300: twiml_raw = yield self._http_request( session['FallbackUrl'], session['FallbackMethod'], data) twiml_raw = yield twiml_raw.content() twiml_parser = TwiMLParser(session['Url']) returnValue(twiml_parser.parse(twiml_raw)) @inlineCallbacks def _handle_connected_call( self, session_id, session, status='in-progress', twiml=None): # TODO: Support sending ForwardedFrom parameter # TODO: Support sending CallerName parameter # TODO: Support sending geographic data parameters session['Status'] = status self.session_manager.save_session(session_id, session) if twiml is None: twiml = yield self._get_twiml_from_client(session) for verb in twiml: if verb.name == "Play": # TODO: Support loop and digit attributes yield self._send_message(verb.nouns[0], session) elif verb.name == "Hangup": yield self._send_message( None, session, TransportUserMessage.SESSION_CLOSE) yield self.session_manager.clear_session(session_id) break elif verb.name == "Gather": # TODO: Support timeout and numDigits attributes msgs = [] for subverb in verb.nouns: # TODO: Support Say and Pause subverbs if subverb.name == "Play": msgs.append({'speech_url': subverb.nouns[0]}) session['Gather_Action'] = verb.attributes['action'] session['Gather_Method'] = verb.attributes['method'] yield self.session_manager.save_session(session_id, session) if len(msgs) == 0: msgs.append({'speech_url': None}) msgs[-1]['wait_for'] = verb.attributes['finishOnKey'] for msg in msgs: yield self._send_message( msg['speech_url'], session, wait_for=msg.get('wait_for')) break def _send_message(self, url, session, session_event=None, wait_for=None): helper_metadata = {'voice': {}} if url is not None: helper_metadata['voice']['speech_url'] = url if wait_for is not None: helper_metadata['voice']['wait_for'] = wait_for return self.send_to( session['To'], None, from_addr=session['From'], session_event=session_event, to_addr_type=TransportUserMessage.AT_MSISDN, from_addr_type=TransportUserMessage.AT_MSISDN, helper_metadata=helper_metadata) @inlineCallbacks def consume_user_message(self, message): # At the moment there is no way to determine whether or not a message # is the result of a wait_for or just a single digit, so if the Gather # data exists inside the current session data, then we assume that it # is the result of a Gather # TODO: Fix this session = yield self.session_manager.load_session(message['from_addr']) if session.get('Gather_Action') and session.get('Gather_Method'): data = self._request_data_from_session(session) data['Digits'] = message['content'] twiml = yield self._get_twiml_from_client({ 'Url': session['Gather_Action'], 'Method': session['Gather_Method'], 'Fallback_Url': None, 'Fallback_Method': None, }, data=data) yield self._handle_connected_call( message['from_addr'], session, twiml=twiml) @inlineCallbacks def consume_ack(self, event): message_id = event['user_message_id'] session_id = yield self.session_lookup.get_address(message_id) yield self.session_lookup.delete_id(message_id) session = yield self.session_manager.load_session(session_id) if session['Status'] == 'queued': yield self._handle_connected_call(session_id, session) @inlineCallbacks def consume_nack(self, event): message_id = event['user_message_id'] session_id = yield self.session_lookup.get_address(message_id) yield self.session_lookup.delete_id(message_id) session = yield self.session_manager.load_session(session_id) if session['Status'] == 'queued': yield self._handle_connected_call( session_id, session, status='failed') @inlineCallbacks def new_session(self, message): yield self.session_lookup.set_id( message['message_id'], message['from_addr']) config = yield self.get_config(message) session = { 'CallId': self.server._get_sid(), 'AccountSid': self.server._get_sid(), 'From': message['from_addr'], 'To': message['to_addr'], 'Status': 'in-progress', 'Direction': 'inbound', 'Url': config.client_path, 'Method': config.client_method, 'StatusCallback': config.status_callback_path, 'StatusCallbackMethod': config.status_callback_method, } yield self.session_manager.create_session( message['from_addr'], **session) twiml = yield self._get_twiml_from_client(session) for verb in twiml: if verb.name == "Play": yield self.reply_to(message, None, helper_metadata={ 'voice': { 'speech_url': verb.nouns[0], } }) elif verb.name == "Hangup": yield self.reply_to( message, None, session_event=TransportUserMessage.SESSION_CLOSE) yield self.session_manager.clear_session(message['from_addr']) break elif verb.name == "Gather": # TODO: Support timeout and numDigits attributes msgs = [] for subverb in verb.nouns: # TODO: Support Say and Pause subverbs if subverb.name == "Play": msgs.append({'speech_url': subverb.nouns[0]}) session['Gather_Action'] = verb.attributes['action'] session['Gather_Method'] = verb.attributes['method'] yield self.session_manager.save_session( message['from_addr'], session) if len(msgs) == 0: msgs.append({'speech_url': None}) msgs[-1]['wait_for'] = verb.attributes['finishOnKey'] for msg in msgs: yield self.reply_to(message, None, helper_metadata={ 'voice': { 'speech_url': msg.get('speech_url'), 'wait_for': msg.get('wait_for'), }}) break @inlineCallbacks def close_session(self, message): # TODO: Implement call duration parameters # TODO: Implement recording parameters session = yield self.session_manager.load_session(message['from_addr']) yield self.session_manager.clear_session(message['from_addr']) url = session.get('StatusCallback') if url and url != 'None': session['Status'] = 'completed' data = self._request_data_from_session(session) yield self._http_request( session['StatusCallback'], session['StatusCallbackMethod'], data)
class SubmitShortMessageProcessor(default.SubmitShortMessageProcessor): CONFIG_CLASS = SubmitShortMessageProcessorConfig def __init__(self, transport, config): super(SubmitShortMessageProcessor, self).__init__(transport, config) self.transport = transport self.redis = transport.redis self.config = self.CONFIG_CLASS(config, static=True) self.session_manager = SessionManager( self.redis, max_session_length=self.config.max_session_length) @inlineCallbacks def handle_outbound_message(self, message, protocol): to_addr = message['to_addr'] from_addr = message['from_addr'] text = message['content'] vumi_message_id = message['message_id'] session_event = message['session_event'] transport_type = message['transport_type'] optional_parameters = {} if transport_type == 'ussd': continue_session = ( session_event != TransportUserMessage.SESSION_CLOSE) session_info = message['transport_metadata'].get( 'session_info', {}) mica_session_identifier = session_info.get( 'session_identifier', '') vumi_session_identifier = make_vumi_session_identifier( to_addr, mica_session_identifier) optional_parameters.update({ 'ussd_service_op': ('02' if continue_session else '17'), 'user_message_reference': ( str(mica_session_identifier).zfill(2)), }) if not continue_session: yield self.session_manager.clear_session( vumi_session_identifier) if self.config.send_long_messages: resp = yield protocol.submit_sm_long( vumi_message_id, to_addr.encode('ascii'), long_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) elif self.config.send_multipart_sar: resp = yield protocol.submit_csm_sar( vumi_message_id, to_addr.encode('ascii'), short_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) elif self.config.send_multipart_udh: resp = yield protocol.submit_csm_udh( vumi_message_id, to_addr.encode('ascii'), short_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) else: resp = yield protocol.submit_sm( vumi_message_id, to_addr.encode('ascii'), short_message=text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters, ) returnValue(resp)
class DeliverShortMessageProcessor(default.DeliverShortMessageProcessor): CONFIG_CLASS = DeliverShortMessageProcessorConfig def __init__(self, transport, config): super(DeliverShortMessageProcessor, self).__init__(transport, config) self.transport = transport self.redis = transport.redis self.config = self.CONFIG_CLASS(config, static=True) self.session_manager = SessionManager( self.redis, max_session_length=self.config.max_session_length) @inlineCallbacks def handle_deliver_sm_ussd(self, pdu, pdu_params, pdu_opts): service_op = pdu_opts['ussd_service_op'] mica_session_identifier = pdu_opts['user_message_reference'] vumi_session_identifier = make_vumi_session_identifier( pdu_params['source_addr'], mica_session_identifier) session_event = 'close' if service_op == '01': # PSSR request. Let's assume it means a new session. session_event = 'new' ussd_code = pdu_params['short_message'] content = None yield self.session_manager.create_session( vumi_session_identifier, ussd_code=ussd_code) elif service_op == '17': # PSSR response. This means session end. session_event = 'close' session = yield self.session_manager.load_session( vumi_session_identifier) ussd_code = session['ussd_code'] content = None yield self.session_manager.clear_session(vumi_session_identifier) else: session_event = 'continue' session = yield self.session_manager.load_session( vumi_session_identifier) ussd_code = session['ussd_code'] content = pdu_params['short_message'] # This is stashed on the message and available when replying # with a `submit_sm` session_info = { 'session_identifier': mica_session_identifier, } decoded_msg = self.dcs_decode(content, pdu_params['data_coding']) result = yield self.handle_short_message_content( source_addr=pdu_params['source_addr'], destination_addr=ussd_code, short_message=decoded_msg, message_type='ussd', session_event=session_event, session_info=session_info) returnValue(result)
class DeliverShortMessageProcessor(default.DeliverShortMessageProcessor): CONFIG_CLASS = DeliverShortMessageProcessorConfig # NOTE: these keys are hexidecimal because of python-smpp encoding # quirkiness ussd_service_op_map = { '01': 'new', '12': 'continue', '81': 'close', # user abort } def __init__(self, transport, config): super(DeliverShortMessageProcessor, self).__init__(transport, config) self.transport = transport self.log = transport.log self.redis = transport.redis self.config = self.CONFIG_CLASS(config, static=True) self.session_manager = SessionManager( self.redis, max_session_length=self.config.max_session_length) @inlineCallbacks def handle_deliver_sm_ussd(self, pdu, pdu_params, pdu_opts): service_op = pdu_opts['ussd_service_op'] mica_session_identifier = pdu_opts['user_message_reference'] vumi_session_identifier = make_vumi_session_identifier( pdu_params['source_addr'], mica_session_identifier) session_event = self.ussd_service_op_map.get(service_op) if session_event == 'new': # PSSR request. Let's assume it means a new session. ussd_code = pdu_params['short_message'] content = None yield self.session_manager.create_session(vumi_session_identifier, ussd_code=ussd_code) elif session_event == 'close': session = yield self.session_manager.load_session( vumi_session_identifier) ussd_code = session['ussd_code'] content = None yield self.session_manager.clear_session(vumi_session_identifier) else: if session_event != 'continue': self.log.warning( ('Received unknown %r ussd_service_op, assuming continue.') % (service_op, )) session_event = 'continue' session = yield self.session_manager.load_session( vumi_session_identifier) ussd_code = session['ussd_code'] content = self.dcs_decode(pdu_params['short_message'], pdu_params['data_coding']) # This is stashed on the message and available when replying # with a `submit_sm` session_info = { 'ussd_service_op': service_op, 'session_identifier': mica_session_identifier, } result = yield self.handle_short_message_content( source_addr=pdu_params['source_addr'], destination_addr=ussd_code, short_message=content, message_type='ussd', session_event=session_event, session_info=session_info) returnValue(result)
class SubmitShortMessageProcessor(default.SubmitShortMessageProcessor): CONFIG_CLASS = SubmitShortMessageProcessorConfig # NOTE: these values are hexidecimal because of python-smpp encoding # quirkiness ussd_service_op_map = { 'continue': '02', 'close': '17', # end } def __init__(self, transport, config): super(SubmitShortMessageProcessor, self).__init__(transport, config) self.transport = transport self.redis = transport.redis self.config = self.CONFIG_CLASS(config, static=True) self.session_manager = SessionManager( self.redis, max_session_length=self.config.max_session_length) @inlineCallbacks def handle_outbound_message(self, message, service): to_addr = message['to_addr'] from_addr = message['from_addr'] text = message['content'] if text is None: text = u"" vumi_message_id = message['message_id'] session_event = message['session_event'] transport_type = message['transport_type'] optional_parameters = {} if transport_type == 'ussd': continue_session = (session_event != TransportUserMessage.SESSION_CLOSE) session_info = message['transport_metadata'].get( 'session_info', {}) mica_session_identifier = session_info.get('session_identifier', '') vumi_session_identifier = make_vumi_session_identifier( to_addr, mica_session_identifier) service_op = self.ussd_service_op_map[( 'continue' if continue_session else 'close')] optional_parameters.update({ 'ussd_service_op': service_op, 'user_message_reference': (str(mica_session_identifier).zfill(2)), }) if not continue_session: yield self.session_manager.clear_session( vumi_session_identifier) resp = yield self.send_short_message( service, vumi_message_id, to_addr.encode('ascii'), text.encode(self.config.submit_sm_encoding), data_coding=self.config.submit_sm_data_coding, source_addr=from_addr.encode('ascii'), optional_parameters=optional_parameters) returnValue(resp)