Skip to main content

Django app to add support for Orange API SMS-MO, SMS-MT/DR

Project description

https://img.shields.io/pypi/v/orangeapisms.svg https://api.travis-ci.org/rgaudin/django-orangeapisms.svg

Django app to add support for Orange API SMS-MO and SMS-MT (with DR)

Install

  • pip install orangeapisms

  • Edit your settings.py file and add:

INSTALLED_APPS = list(INSTALLED_APPS) + ['orangeapisms', 'django_forms_bootstrap']
  • Configure your orangeapi.json file (place it next to your settings.py file):

{
    "handler_module": "myapp.orange_handler",
    "use_db": true,
    "sender_address": "+22300000000",
    "sender_name": "POTUS",
    "client_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "client_secret": "xxxxxxxxxxxxxxxx",
    "enable_tester": true,
    "default_sender_name": "sender_address"
}
  • Setup Database with ./manage.py migrate

That’s it ! Test it by accessing /oapi/ and playing with the tester.

client_id:

Your Client ID (mandatory)

client_secret:

Your Client Secret (mandatory)

handler_module:

python path to your module handling messages (mandatory)

use_db:

whether to store SMS in DB (SMSMessage Model)

smsmt_url:

URL of your API (might change depending on your plan)

oauth_url:

OAuth URL for Orange API

sender_address:

Your subscribed phone number

sender_name:

Your custom sender name (can be number or string)

enable_tester:

To enable tester & logs WebUI on /oapi/

default_sender_name:

What to use as default sender name

send_async:

whether to deffer SMS sending to celery

celery_module:

python path to your celery tasks module

country:

ISO 3166-1 code for your country (used for balance checking)

fix_msisdn:

whether to fix SMS-MT destination without prefix

country_prefix:

MSISDN numeric prefix for your country (to fix SMS-MT without prefix)

Usage

After installation (previous step), you are able to send & receive individual SMS. To automatically process incoming SMS, you will have to customise the handler module which you specified in ORANGE_API[‘handler_module’].

The module would call three different functions based on events:

  • smsmo(message) on an incoming SMS-MO

  • smsmt(message) on an outgoing (sent by you) SMS-MT

  • smsdr(message) on an incoming delivery-receipt notification. The passed message is the SMS-MT which received the DR.

Sample handler module:

import datetime
import logging

from orangeapisms.utils import send_sms
from myapp.models import UserModel

logger = logging.getLogger(__name__)


def handle_smsmo(message):
    logger.info("Received an SMS-MO: {}".format(message))

    def register_user(message, keyword, text):
        # break-down the formatted SMS into variables
        try:
            name, sex, dob = text.split()
        except:
            return message.reply('Invalid format')

        # valid user entries
        if sex not in ['m', 'f']:
            return message.reply('Unable to understand sex')

        # reuse input into different data structure
        try:
            d = dob.split('-')
            birthdate = datetime.datetime(d[3], d[2], d[1])
        except:
            return message.reply('Unable to understand date of birth')

        # make use of the data including message metadata
        user = UserModel.objects.create(
            name=name, sex=sex, dob=birthdate,
            phone=message.sender_address)

        return message.reply("Congratulations, you're registered as #{}"
                             .format(user.id))

    def broadcast_to_users(message, keyword, text):
        # loop on all Users in DB
        for user in UserModel.objects.all():
            # send a custom message to that user
            send_sms(user.phone, "Hey {u}, {c}".format(u=user.name, c=text))

    keywords = {
        'register': register_user,
        'broadcast': broadcast_to_users,
    }

    # find the proper keyword
    keyword, text = message.content.split(' ', 1)
    if keyword in keywords.keys():
        return keywords.get(keyword)(message, keyword, text.strip().lower())

    # fallback on error
    return message.reply('Unknown request')


def handle_smsmt(message):
    logger.info("Sent an SMS-MT: {}".format(message))


def handle_smsdr(message):
    logger.info("Received an SMS-DR: {}".format(message))

Using a broker to send SMS-MT

By default, SMS-MT are sent synchronously meaning your request is stalled until the API call is complete.

If you need to send multiple SMS-MT while not blocking the request thread, you will want to defer sending to a broker.

This library integrates easily with celery so you can do just that in a breeze.

To use Asynchronous SMS-MT sending, you will need to :

  • Install and configure celery onto your project (see instructions bellow if needed)

  • Edit your settings.py to include the following options

# wether to send asynchronously or not
'send_async': True,
# python path of your celery module containing the task
'celery_module': 'myproject.celery'
  • Add a custom task to your celery module

@app.task()
def submit_sms_mt_request_task(payload, message):
    from orangeapisms.utils import do_submit_sms_mt_request
    return do_submit_sms_mt_request(payload, message)

That’s it. Now every SMS-MT will be deferred to celery and processed by your broker.

Launch a celery worker to test it!

Basic celery configuration

If you are not familiar with celery and want to quickly test the async feature, follow this steps:

  • Install redis on your computer and start it

sudo apt-get install redis
service redis start
  • Install celery and redis with `pip install celery redis`

  • Add the celery configuration to your settings.py:

BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
  • Create a module in your project for celery:

import os

from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
app = Celery('project')
app.config_from_object('django.conf:settings')


@app.task()
def submit_sms_mt_request_task(payload, message):
    from orangeapisms.utils import do_submit_sms_mt_request
    return do_submit_sms_mt_request(payload, message)
  • Launch a worker

celery -A project worker -l info

Project details


Release history Release notifications | RSS feed

This version

0.28

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

orangeapisms-0.28.tar.gz (17.8 kB view details)

Uploaded Source

File details

Details for the file orangeapisms-0.28.tar.gz.

File metadata

  • Download URL: orangeapisms-0.28.tar.gz
  • Upload date:
  • Size: 17.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for orangeapisms-0.28.tar.gz
Algorithm Hash digest
SHA256 c9aa5f4a117bbecaec2d0fd4a994556327ebe0e4dd6aa0b85b810cadc3b9ceb7
MD5 200a3f047c0a305762a5a7660d212553
BLAKE2b-256 c45af3b7863dd50eb1042ae5899972146e3cefe6869d65f64ba85916d8e3b802

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page