def message_resend(request, message_id): """ Re-sends the given message """ message = get_object_or_404(Message, pk=message_id) contact = message.contact if request.method == 'POST': form = ResendForm(request.POST) if form.is_valid(): text = form.cleaned_data['text'] number = contact.contactprofile.get_phone_number() connection = lookup_connections(settings.MODERATOR_BACKEND, [number])[0] receive(text, connection) messages.success( request, _("The message %(text)s was successfully resent") % {'text': unicode(text)}) return HttpResponseRedirect( reverse("moderation.views.contact", args=(contact.pk, ))) else: form = ResendForm(initial={'text': message.text}) return render_to_response("message_resend.html", { 'contact': contact, 'message': message, 'form': form, }, context_instance=RequestContext(request))
def message_received(request, backend_name): """Handle HTTP requests from TextIt. """ try: backend = settings.INSTALLED_BACKENDS[backend_name] except KeyError: logger.error('Name "{}" not found in settings INSTALLED_BACKENDS.'.format(backend_name)) return HttpResponseBadRequest('Name "{}" not found in settings INSTALLED_BACKENDS.'.format(backend_name)) try: if request.META['QUERY_STRING'] != backend['config']['query_key']: r = 'query_key "{}" does not match configured value from django settings "{}"'.format( request.META['QUERY_STRING'], backend['config']['query_key']) logger.error(r) return HttpResponseBadRequest(r) except KeyError: logger.error("No query_key set up in settings INSTALLED_BACKENDS[backend_name]") return HttpResponseBadRequest("No query_key set up in settings INSTALLED_BACKENDS[backend_name]") post = request.POST logger.debug("@@ request from TextIt - Decoded data: %r" % post) try: post_event = post['event'] except KeyError: logger.error('No "Event" key in POST request') return HttpResponseBadRequest("No Event key in POST request") if post_event == 'mo_sms': # Must have received a message logger.debug("@@Got a text message") try: fa = post['phone'] from_address = fa[1:] if fa.startswith('+') else fa # strip off the plus sign text = post['text'] logger.debug("@@Received message from %s: %s" % (from_address, text)) except KeyError: logger.exception('Malformed POST message') return HttpResponseBadRequest("Malformed POST message") try: # get (or create) a connections object for this backend and from_address connections = lookup_connections(backend_name, [from_address]) except Exception as e: r = "Error finding connection for backend_name={}, from={}, err={}".format( backend_name, from_address, e) logger.error(r) return HttpResponseServerError(r) try: # pass the message to RapidSMS receive(text, connections[0]) except Exception as e: r = "Error receiving message. backend_name={}, from={}, err={}".format( backend_name, from_address, e) logger.error(r) return HttpResponseServerError(r) # Respond nicely to TextIt return HttpResponse("OK") # elif: if post_event in ['mt_sent', 'mt_dlvd']: return HttpResponse("thanks") # confirmation messages are ignored # else: logger.error("@@No recognized command in request from TextIt") return HttpResponseBadRequest("Unexpected event code='{}'".format(post_event))
def test_outgoing(self): """Eager backends should call rapidsms_handle_message directly""" with patch('rapidsms.router.celery.tasks.rapidsms_handle_message') as mock_method: connections = self.lookup_connections(identities=['1112223333']) receive("test", connections[0]) mock_method.assert_called_once()
def test_outgoing(self): """Eager backends should call rapidsms_handle_message directly""" with patch('rapidsms.router.celery.tasks.rapidsms_handle_message' ) as mock_method: connections = self.lookup_connections(identities=['1112223333']) receive("test", connections[0]) mock_method.assert_called_once()
def form_valid(self, form): """ If the form validated successfully, passes the message on to the router for processing. """ data = form.get_incoming_data() receive(**data) return HttpResponse('OK')
def store_and_queue(identity, text): """Store a message in our log and send it into RapidSMS. :param identity: Phone number the message will appear to come from :param text: The message text """ store_message(INCOMING, identity, text) connection = lookup_connections(BACKEND_NAME, [identity])[0] receive(text, connection)
def store_and_queue(identity, text, to_addr=None): """Store a message in our log and send it into RapidSMS. :param identity: Phone number the message will appear to come from :param text: The message text :param to_addr: Phone number that the message is sent to """ store_message(INCOMING, identity, text) connection = lookup_connections(BACKEND_NAME, [identity])[0] receive(text, connection, fields={"to_addr": to_addr, "from_addr": identity})
def store_and_queue(backend_name, identity, text): """Store a message in our log and send it into RapidSMS. :param backend_name: :param identity: Phone number the message will appear to come from :param text: The message """ from rapidsms.router import receive, lookup_connections store_message(HttpTesterMessage.INCOMING, identity, text) connection = lookup_connections(backend_name, [identity])[0] receive(text, connection)
def send_message(request): form = forms.MessageForm(request.POST) if form.is_valid(): cd = form.cleaned_data identity = cd["identity"] connection = lookup_connections("message_tester", [identity])[0] receive(cd["text"], connection) return {"success": True} else: return {"error": u"Parâmetros obrigatórios não encontrados"}
def store_and_queue(identity, text, to_addr=None): """Store a message in our log and send it into RapidSMS. :param identity: Phone number the message will appear to come from :param text: The message text :param to_addr: Phone number that the message is sent to """ store_message(INCOMING, identity, text) connection = lookup_connections(BACKEND_NAME, [identity])[0] receive(text, connection, fields={ 'to_addr': to_addr, 'from_addr': identity })
def test_incoming(self): """Received messages should call _queue_message with incoming=True""" with patch.object(CeleryRouter, '_queue_message') as mock_method: connections = self.lookup_connections(identities=['1112223333']) message = receive("test", connections[0]) mock_method.assert_called_once_with(message, incoming=True)
def handle_message(self): event_kwargs = self.get_model_kwargs('from','message','timestamp') #fix variables for model event_kwargs['sender'] = event_kwargs.pop('from') connection = lookup_connections('envaya', [event_kwargs['sender']])[0] msg_in = receive(event_kwargs['message'],connection) return EnvayaOutgoingResponse()
def form_valid(self, form): """ If the form validated successfully, passes the message on to the router for processing. """ data = form.get_incoming_data() self.logger.debug("data that we got is %s" % data) if data['action'] == 'incoming': receive(text = data['text'], connection = data['connection']) self.logger.info("Incoming message forwarded to router successfully!") elif data['action'] == 'outgoing': self.logger.info("No outgoing message to forward to EnvayaSMS Android app!") return HttpResponse(json.dumps({'events': data['events']}), content_type='application/json')
def test_saved_message_fields_receive(self): """Extra data should persist through receive.""" connection = self.create_connection() fields = {'extra-field': 'extra-value'} message = receive('test incoming message', connection=connection, fields=fields) self.assertTrue('extra-field' in message.fields) self.assertEqual(message.fields['extra-field'], fields['extra-field'])
def form_valid(self, form): data = form.get_incoming_data() message = receive(**data) if hasattr(message, 'responses'): response_body = u' '.join([r['text'] for r in message.responses]) return HttpResponse(response_body, content_type='text/plain; charset=utf-8') return HttpResponse('')
def send(message,i=0): connection = router.lookup_connections(BACKEND,[message['identity']])[0] msg_in = router.receive(message['message'],connection) msg_in.ccem_msg.created = message['date'] msg_in.ccem_msg.save() msg_out = msg_in.connections[0].messages.all()[0] msg_out.created = message['date']+datetime.timedelta(seconds=10) msg_out.save() print 'Sent',i,':',message['message'] return msg_in
def handle_message(self): event_kwargs = self.get_model_kwargs('from','message','timestamp') #fix variables for model event_kwargs['sender'] = event_kwargs.pop('from') connection = lookup_connections('envaya', [event_kwargs['sender']])[0] msg_in = receive(event_kwargs['message'],connection) #send response via http call back events = [{'event':'send','messages':[],},] msgs_out = [] for response in msg_in.responses: #msgs_out.append(send(**response)) #send is called when we process the msg, no need to call it again here events[0]['messages'].append({ 'to':response['connections'][0].identity, 'message':response['text'] }) #models.SMS(**event_kwargs).save() logger.debug("Send Envaya:\n%s",json.dumps({'events':events})) return HttpResponse(json.dumps({'events':events}),mimetype='application/json')
def handle_message(self): event_kwargs = self.get_model_kwargs('from', 'message', 'timestamp') #fix variables for model event_kwargs['sender'] = event_kwargs.pop('from') connection = lookup_connections('envaya', [event_kwargs['sender']])[0] msg_in = receive(event_kwargs['message'], connection) #send response via http call back events = [ { 'event': 'send', 'messages': [], }, ] msgs_out = [] for response in msg_in.responses: #msgs_out.append(send(**response)) #send is called when we process the msg, no need to call it again here events[0]['messages'].append({ 'to': response['connections'][0].identity, 'message': response['text'] }) #models.SMS(**event_kwargs).save() logger.debug("Send Envaya:\n%s", json.dumps({'events': events})) return HttpResponse(json.dumps({'events': events}), mimetype='application/json')
def store_and_queue(backend_name, identity, text): from rapidsms.router import receive, lookup_connections store_message('in', identity, text) connection = lookup_connections(backend_name, [identity])[0] receive(text, connection)
def receive_multimodem_message(request, server_slug): """ The view to handle requests from multimodem has to be custom because the server can post 1-* messages in a single request. The Rapid built-in class-based views only accept a single message per form/post. TODO: Add basic auth to validate against Rapid's user database. The iSMS modem only supports basic auth. :param request: :return: """ xml_data = request.POST.get('XMLDATA', '') """ The modem posts the data as it receives it formatted as an xml file. The xml is then URL encoded and posted as a form parameter called XML data. Decoded Example: <?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <Response> <Msg_Count>2</Msg_Count> <MessageNotification> <Message_Index>1</Message_Index> <ModemNumber>2:111222333</ModemNumber> <SenderNumber>+222333333</SenderNumber> <Date>15/04/13</Date> <Time>10:55:58</Time> <EncodingFlag>ASCII</EncodingFlag> <Message>Testn2</Message> </MessageNotification> <MessageNotification> <Message_Index>2</Message_Index> <ModemNumber>2:111222333</ModemNumber> <SenderNumber>+222333333</SenderNumber> <Date>15/04/13</Date> <Time>10:58:39</Time> <EncodingFlag>Unicode</EncodingFlag> <Message>0429043D043F0437043D043C0433043C0436043D043C</Message> </MessageNotification> </Response> """ try: root = ET.fromstring(xml_data) except ET.ParseError: logger.error("Failed to parse XML") logger.error(request) return HttpResponseBadRequest('Error parsing XML') for message in root.findall('MessageNotification'): raw_text = message.find('Message').text from_number = message.find('ModemNumber').text # ModemNumber is simply 1 for single-port modems and it's a string of # 'port_numer:phone_number' for multiport modems. if ':' in from_number: modem_number, phone_number = from_number.split(':')[0:2] else: # This is a single port modem modem_number = from_number # Search through backends looking for the single one with this # server_slug / modem combo possible_backends = getattr(settings, 'INSTALLED_BACKENDS', {}).items() backend_names = [name for name, config in possible_backends if str(config.get('modem_port')) == str(modem_number) and config.get('server_slug') == server_slug] if backend_names: if len(backend_names) > 1: logger.error("More than 1 backend with this server/port combo: %s / %s", server_slug, modem_number) return HttpResponseBadRequest('Improper Configuration: multiple backends with same server / port') backend_name = backend_names[0] encoding = message.find('EncodingFlag').text if encoding.lower() == "unicode": msg_text = ismsformat_to_unicode(raw_text) else: msg_text = raw_text connections = lookup_connections(backend_name, [message.find('SenderNumber').text]) data = {'text': msg_text, 'connection': connections[0]} receive(**data) else: logger.error("Can't find backend for this server/port combo: %s / %s", server_slug, modem_number) return HttpResponseBadRequest('Unknown server or port.') return HttpResponse('OK')
def sendMessage(self, num, txt, date=None): if date is None: date = datetime.now() connection = self.lookup_connections([num])[0] receive(txt, connection)
def receive_multimodem_message(request, server_slug): """ The view to handle requests from multimodem has to be custom because the server can post 1-* messages in a single request. The Rapid built-in class-based views only accept a single message per form/post. TODO: Add basic auth to validate against Rapid's user database. The iSMS modem only supports basic auth. :param request: :return: """ xml_data = request.POST.get('XMLDATA', '') """ The modem posts the data as it receives it formatted as an xml file. The xml is then URL encoded and posted as a form parameter called XML data. Decoded Example: <?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <Response> <Msg_Count>2</Msg_Count> <MessageNotification> <Message_Index>1</Message_Index> <ModemNumber>2:111222333</ModemNumber> <SenderNumber>+222333333</SenderNumber> <Date>15/04/13</Date> <Time>10:55:58</Time> <EncodingFlag>ASCII</EncodingFlag> <Message>Testn2</Message> </MessageNotification> <MessageNotification> <Message_Index>2</Message_Index> <ModemNumber>2:111222333</ModemNumber> <SenderNumber>+222333333</SenderNumber> <Date>15/04/13</Date> <Time>10:58:39</Time> <EncodingFlag>Unicode</EncodingFlag> <Message>0429043D043F0437043D043C0433043C0436043D043C</Message> </MessageNotification> </Response> """ try: root = ET.fromstring(xml_data) except ET.ParseError: logger.error("Failed to parse XML") logger.error(request) return HttpResponseBadRequest('Error parsing XML') for message in root.findall('MessageNotification'): raw_text = message.find('Message').text from_number = message.find('ModemNumber').text # ModemNumber is simply 1 for single-port modems and it's a string of # 'port_numer:phone_number' for multiport modems. if ':' in from_number: modem_number, phone_number = from_number.split(':')[0:2] else: # This is a single port modem modem_number = from_number # Search through backends looking for the single one with this # server_slug / modem combo possible_backends = getattr(settings, 'INSTALLED_BACKENDS', {}).items() backend_names = [ name for name, config in possible_backends if str(config.get('modem_port')) == str(modem_number) and config.get('server_slug') == server_slug ] if backend_names: if len(backend_names) > 1: logger.error( "More than 1 backend with this server/port combo: %s / %s", server_slug, modem_number) return HttpResponseBadRequest( 'Improper Configuration: multiple backends with same server / port' ) backend_name = backend_names[0] encoding = message.find('EncodingFlag').text if encoding.lower() == "unicode": msg_text = ismsformat_to_unicode(raw_text) else: msg_text = raw_text connections = lookup_connections( backend_name, [message.find('SenderNumber').text]) data = {'text': msg_text, 'connection': connections[0]} receive(**data) else: logger.error( "Can't find backend for this server/port combo: %s / %s", server_slug, modem_number) return HttpResponseBadRequest('Unknown server or port.') return HttpResponse('OK')
def receive(self, text, connection, fields=None): """ A wrapper around the ``receive`` API. See :ref:`receiving-messages`.""" return receive(text, connection, fields)
def receive(self, text, connection, fields=None): """receive() API wrapper.""" return receive(text, connection, fields)
def receive(self, text, connection, **kwargs): """ A wrapper around the ``receive`` API. See :ref:`receiving-messages`. """ return receive(text, connection, **kwargs)