Skip to content

Commit

Permalink
Incoming message url (#3)
Browse files Browse the repository at this point in the history
- delete test database
- ignore test database
- Added reply url, fixed inbound save problem
  • Loading branch information
mastizada authored Jan 20, 2017
1 parent b0bbc5b commit b164fa6
Show file tree
Hide file tree
Showing 11 changed files with 98 additions and 34 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,7 @@ NOTE.md

# Example project
venv/
example/sqlite.db
example/debug.log
environment.conf
environment.sh
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changes
-------

# 1.3.0

* Added url for inbound messages (receive sms messages)
* Fixed problem with IncomingSMSView
* Improved test project (logging and settings improvements)

# 1.2.0

* Fixed setup using django documentations (included migrations folder)
Expand Down
14 changes: 5 additions & 9 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ Used for SMS messages in SiteLedger project.
Quickstart
----------

1. Include ``dj-twilio-sms`` in your ``requirements.txt`` file.
1. Install ``dj-twilio-sms`` using ``pip``.

2. Add ``dj_twilio_sms`` to ``INSTALLED_APPS`` and migrate (manage.py migrate).
2. Add ``dj_twilio_sms`` to ``INSTALLED_APPS`` and migrate (``manage.py migrate``).

3. Add the following url to your urlconf:

Expand All @@ -31,15 +31,11 @@ Quickstart
url(r"^messaging/", include("dj_twilio_sms.urls")),
this will receive confirmation callbacks for any SMS message
that you send using ``utils.send_sms``.
that you send using ``utils.send_sms`` also will receive incoming messages.

4. Create a new view and override ``IncomingSMSView.post_save(self, obj)`` method
to receive SMS messages via callbacks from Twilio. The received ``obj``
param will be an instance of ``IncomingSMS`` model.
4. Configure Twilio callback to send notifications to the above view's url. (ex: ``/messaging/reply/`` for inbound messages)

5. Configure Twilio callback to send notifications to the above view's url.

6. Configure settings:
5. Configure settings:

- TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_PHONE_NUMBER - copy
credentials from the Twilio panel.
Expand Down
25 changes: 25 additions & 0 deletions dj_twilio_sms/migrations/0002_auto_20170120_0334.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-01-20 01:34
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('dj_twilio_sms', '0001_initial'),
]

operations = [
migrations.AlterField(
model_name='incomingsms',
name='from_city',
field=models.CharField(blank=True, default='', max_length=100),
),
migrations.AlterField(
model_name='incomingsms',
name='from_state',
field=models.CharField(blank=True, default='', max_length=100),
),
]
4 changes: 2 additions & 2 deletions dj_twilio_sms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ class IncomingSMS(models.Model):
sms_sid = models.CharField(max_length=34)
account_sid = models.CharField(max_length=34)
from_number = models.CharField(max_length=30)
from_city = models.CharField(max_length=30, default="", blank=True)
from_state = models.CharField(max_length=30, default="", blank=True)
from_city = models.CharField(max_length=100, default="", blank=True)
from_state = models.CharField(max_length=100, default="", blank=True)
from_zip = models.CharField(max_length=30, default="", blank=True)
from_country = models.CharField(max_length=120, default="", blank=True)
to_number = models.CharField(max_length=30)
Expand Down
18 changes: 10 additions & 8 deletions dj_twilio_sms/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@


class SMSRequestSerializer(serializers.ModelSerializer):
SmsSid = serializers.CharField(max_length=34, required=True, source="sms_sid")
MessageSid = serializers.CharField(max_length=34, required=True, source="sms_sid")
AccountSid = serializers.CharField(max_length=34, required=True, source="account_sid")
From = serializers.CharField(max_length=30, required=True, source="from_number")
FromCity = serializers.CharField(max_length=30, required=False, source="from_city")
FromState = serializers.CharField(max_length=30, required=False, source="from_state")
FromZip = serializers.CharField(max_length=30, required=False, source="from_zip")
FromCountry = serializers.CharField(max_length=120, required=False, source="from_country")
To = serializers.CharField(max_length=30, required=True, source="to_number")
Body = serializers.CharField(max_length=160, required=True, source="body")
FromCity = serializers.CharField(max_length=100, required=False, source="from_city")
FromState = serializers.CharField(max_length=100, required=False, source="from_state")
FromZip = serializers.CharField(max_length=30, required=False, source="from_zip")
FromCountry = serializers.CharField(max_length=120, required=False, source="from_country")

# @TODO Add MessagingServiceSid and NumMedia

class Meta:
model = IncomingSMS
fields = [
"SmsSid", "AccountSid", "From", "FromCity", "FromState", "FromZip",
"FromCountry", "To", "Body"
"MessageSid", "AccountSid", "From", "To", "Body",
"FromCity", "FromState", "FromZip", "FromCountry"
]


Expand All @@ -31,5 +33,5 @@ class SMSStatusSerializer(serializers.ModelSerializer):
class Meta:
model = OutgoingSMS
fields = [
"SmsSid", "SmsStatus",
"SmsSid", "SmsStatus"
]
3 changes: 2 additions & 1 deletion dj_twilio_sms/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

from __future__ import unicode_literals
from django.conf.urls import url
from .views import sms_status_callback_view
from .views import sms_status_callback_view, IncomingSMSView

urlpatterns = [
url(r"^callback/sent/(?P<pk>\d+)/$", sms_status_callback_view, name="sms_status_callback"),
url(r"^reply/$", IncomingSMSView.as_view(), name="sms_inbound"),
]
8 changes: 7 additions & 1 deletion dj_twilio_sms/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from django.http import HttpResponse
from django.views.generic import View
from django.views.generic.detail import SingleObjectMixin
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from rest_framework import status
from twilio import twiml

Expand All @@ -22,6 +24,10 @@ class TwilioView(View):

response_text = None

@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super(TwilioView, self).dispatch(request, *args, **kwargs)

def get_data(self):
return self.request.POST

Expand Down Expand Up @@ -58,7 +64,7 @@ def handle_request(self, data):

serializer = SMSRequestSerializer(data=data)
if serializer.is_valid():
self.object = serializer.save(force_insert=True)
self.object = serializer.save()
self.post_save(self.object)
else:
logger.error(
Expand Down
50 changes: 38 additions & 12 deletions example/settings.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Django settings for dj_twilio_sms project.
import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
DEBUG = True
SMS_DEBUG = DEBUG
Expand All @@ -9,13 +10,27 @@
'default': {
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'sqlite.db', # Or path to database file if using sqlite3.
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used with sqlite3.
}
}

LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': os.path.join(PROJECT_DIR, 'debug.log'),
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'DEBUG',
'propagate': True,
},
},
}
ALLOWED_HOSTS = ['*']
TIME_ZONE = 'Asia/Jerusalem'
USE_TZ = True
LANGUAGE_CODE = 'en-us'
Expand All @@ -32,22 +47,33 @@
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
SECRET_KEY = 'Secret@Test'
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
ROOT_URLCONF = 'urls'

TEMPLATE_DIRS = ()

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
Expand Down
Binary file removed example/sqlite.db
Binary file not shown.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from setuptools import setup, find_packages
import os

version = "1.2.0"
version = "1.3.0"

with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as f:
README = f.read()
Expand Down

0 comments on commit b164fa6

Please sign in to comment.