Working with Messages

It’s all well and good just being able to receive messages, but once a message has been received, how do you work with it?

To help work with messages, pyrowire relies on handlers; methods assigned to a specific message topic.

Handlers

With pyrowire, the only logic you need to think about (other than optional message validators), is what happens to the message after it’s been successfully received. Enter the handler method, a function that defines the business logic for your application, and is annotated:

@pyrowire.handler(topic='whatever_topic_it_is_for')

where ‘whatever_topic_its_for’ corresponds to a defined topic block in your settings file.

Defining a Handler

Defining a handler is super easy. Just annotate a method that takes a message, performs your topic-specific logic, and does whatever else it needs to do.

@pyrowire.handler(topic='my_topic')
def my_handler(message_data):
    if not message_data:
        raise TypeError("message_data must not be None")
    # handler logic
    return message_data

Handler Criteria

All handlers must satisfy the following criteria:

  1. the pyrowire.handler annotation must take one kwarg, topic, and must be set to the topic for which the handler is to work (this topic must be in your settings file).
  2. the method definition must take one arg, message_data
  3. the method should return the message_data object

Sample Handler

Let’s take a look at a very simple handler that just receives an incoming message, randomizes the order, then returns it:

# all app.handler methods need to be annotated with the topic for which they process
# and take one kwarg, 'message_data'
@pyrowire.handler(topic='sms_randomizer')
def my_handler(message_data):
    if not message_data:
        raise TypeError("message_data must not be None")

    import random
    # randomize the message and save it as 'return_message'
    message = message_data['message'].split()
    random.shuffle(message)
    message_data['reply'] = ' '.join(message)

    # send the message data back along with the key of the message body
    # to send to initiate a Twilio SMS reply
    pyrowire.sms(message_data)

    return message_data

As you can see, all we need to do to process and return a message is tell a method annotated with @pyrowire.handler``(topic='my_topic_name') what to do with the message data that is received from the pyrowire app worker, then send it using pyrowire.sms method. To use this method, we pass the message_data object back to the sms method. By default the key used to source the message to send is ‘reply’, but this can be changed by adding an optional kwarg, ‘key’.

See below, Changing the Reply Key for more information.

Sending a Message

pyrowire supports sending both SMS and MMS, both using a very simple syntax. Currently, to send MMS in the US and UK, you need a shortcode, but in Canada you can use either a shortcode or a full phone number.

Replying with SMS

All message objects that you work with will by default have a reply property, which you can populate with the reply message you wish to send back to the original sender. You can also use your own key for a message, if you pass it to the pyrowire.sms method as a kwarg. Let’s take a look:

@pyrowire.handler(topic='sample')
def sample_handler(message_data):
    if not message_data:
        raise TypeError("message_data must not be None")

    reply = ''
    for index, item in enumerate([x for x in message_data['message'].split()]):
        if index % 2 == 0:
           reply += ' foo%s' % item
        else:
            reply += ' bar%s' % item
    message_data['reply'] = reply.strip()

    # here's where you send back
    pyrowire.sms(message_data)

    return message_data

So that’s it. Just add pyrowire.sms(message_data) before the return, and an SMS will be returned back to the original sender with the ‘reply’ key as the message body.

Replying with MMS

pyrowire is rigged up to support MMS as well.

To send an MMS message, you just substitute pyrowire.sms method with pyrowire.mms.

@pyrowire.handler(topic='sample')
def random_cat_image(message_data):
    if not message_data:
        raise TypeError("message_data must not be None")

    import random
    import mycats
    url = random.choice(mycats.images)

    # here's where you send back
    pyrowire.mms(message_data, media_url=url)

    return message_data

If you want to include text with the media message, you can do so by setting a reply, and using the include_text kwarg:

@pyrowire.handler(topic='sample')
def random_cat_image(message_data):
    if not message_data:
        raise TypeError("message_data must not be None")

    import random
    import mycats
    url = random.choice(mycats.images)

    # adding an additional reply message
    message_data['reply'] = "Meeeeeeeeeowww!"

    # here's where you send back
    pyrowire.mms(message_data, include_text=True, media_url=url)

    return message_data

Changing the Reply Key

If you would like, you can change the reply key from ‘reply’ to a key of your choice. All you need to do to use it with either pyrowire.sms or pyrowire.mms is add a kwarg:

# for sms
pyrowire.sms(message_data, key='my_custom_key')

# for mms
pyrowire.mms(message_data,
             key='my_custom_key',
             include_text=True,
             media_url='http://bit.ly/IC394d')