djmessenger package¶
Subpackages¶
Submodules¶
djmessenger.admin module¶
djmessenger.apps module¶
djmessenger.exceptions module¶
-
exception
djmessenger.exceptions.
DJMException
¶ Bases:
Exception
Base Exception for DJM
-
exception
djmessenger.exceptions.
DJMInvalidConfigException
¶ Bases:
djmessenger.exceptions.DJMException
This exception will be raised if user tried to do something that breaks the assumption made by Facebbok. For example, threading setting greeting text can have only one, if the user tried to add more, raise this exception
-
exception
djmessenger.exceptions.
DJMInvalidValueException
¶
djmessenger.facebook_locales module¶
An enum to represent locales that Facebook supports
-
class
djmessenger.facebook_locales.
FacebookLocale
¶ Bases:
enum.Enum
djmessenger.filtering module¶
Filtering Module¶
Filtering module defines a BaseFilter
as the most basic abstract class
and all its subclasses provide some specific logic to filter a given
djmessenger.receiving.Messaging
object
-
class
djmessenger.filtering.
AuthenticationFilter
¶ Bases:
djmessenger.filtering.BaseFilter
-
should_pass
(messaging)¶
-
-
class
djmessenger.filtering.
BaseFilter
¶ Bases:
djmessenger.utils.serializable.Serializable
BaseFilter is an ABC for filters, it defines an abstract method which takes a Messaging object and returns a bool to indicate whether this Messaging should be further processed
-
should_pass
(messaging)¶ Takes a
djmessenger.receiving.Messaging
object and determines whether this object should pass this filter and continueParameters: messaging (djmessenger.receiving.Messaging) – A Messaging instance to filter against Returns: True if the given messaging passed this filter and should continue with the next operation; False otherwise Return type: bool
-
-
class
djmessenger.filtering.
EmailFilter
¶ Bases:
djmessenger.filtering.BaseFilter
Filter that the text sent by user is a valid email address
-
should_pass
(messaging)¶
-
-
class
djmessenger.filtering.
LocationFilter
¶ Bases:
djmessenger.filtering.BaseFilter
Pass if messaging is a Location
-
should_pass
(messaging)¶
-
-
class
djmessenger.filtering.
MultimediaFilter
¶ Bases:
djmessenger.filtering.BaseFilter
Pass if messaging is multimedia
-
should_pass
(messaging)¶
-
-
class
djmessenger.filtering.
PostbackFilter
¶ Bases:
djmessenger.filtering.BaseFilter
Pass if messaging is a POSTBACK
-
should_pass
(messaging)¶
-
-
class
djmessenger.filtering.
SimpleTextRegexFilter
(regex=None)¶ Bases:
djmessenger.filtering.BaseFilter
Pass if messaging has a text that matches the regex
An example in
djmessenger.utils.default_routing_policy
{ "name": "djmessenger.filtering.SimpleTextRegexFilter", "args": { "regex": "^你好$" } }
-
should_pass
(messaging)¶
-
-
class
djmessenger.filtering.
StickerFilter
¶ Bases:
djmessenger.filtering.BaseFilter
Pass if messaging is a STICKER and the id is within STICKER_IDS
-
STICKER_IDS
= ()¶
-
should_pass
(messaging)¶
-
-
class
djmessenger.filtering.
ThumbUpFilter
¶ Bases:
djmessenger.filtering.StickerFilter
-
STICKER_IDS
= ('810', '814', '822')¶
-
-
class
djmessenger.filtering.
TimeFilter
(start_time, end_time)¶ Bases:
djmessenger.filtering.BaseFilter
Filter that passes if the messaging timestamp is within the predefined time period
An example in policy
{ "name": "djmessenger.filtering.TimeFilter", "args": { "start_time": "2016-1-1T00:00:00Z-0800", "end_time": "2017-1-1T01:00:00Z-0800" } }
-
FORMAT
= '%Y-%m-%dT%H:%M:%SZ%z'¶
-
should_pass
(messaging)¶
-
djmessenger.handling module¶
Handling Module¶
Handling module provides abstract class and some implementation for handling a
djmessenger.receiving.Messaging
object. Handling means to do internal
operations against the Messaging
object, eg. save something into database,
and etc
BaseHandler¶
Defines handle(messaging) which need to be overridden by subclasses
In handle(), you just perform operations on the data provided by messaging
-
class
djmessenger.handling.
BaseHandler
¶ Bases:
abc.ABC
BaseHandler is an abstract base class to
Actually handle it by adding something to database, or other internal work
-
handle
(messaging)¶ Actually handles the messaging
Parameters: messaging (djmessenger.receiving.Messaging) – A Messaging object to handle Returns: nothing
-
-
class
djmessenger.handling.
BasePayloadHandler
¶ Bases:
djmessenger.handling.BaseHandler
Postback and QuickReply contains payload, and in order to support request chaining, we need to provide a default base class for Postback and QuickReply.
Since the payload in Postback and QuickReply is merely a simple string limited to 1000 chars, we can utilize this space to send some bookkeeping info to achieve request chaining.
We are going to make the payload (which is a plain text) looks like a valid json object so that we can deserialize it back to a dict and then we can figure out which handler was the sender, then do corresponding actions
-
get_payload
(messaging)¶ Payload class must be a subclass of djmessenger.utils.payload.Payload, and the class defines an attribute payload_class, we can simply load the class from this fully qualified class name
Returns: an instance of the subclass of Payload Return type: an instance of the subclass of Payload
-
get_payload_string_from_messaging
(messaging)¶ Returns payload contained in
djmessenger.receiving.Messaging
Returns: the corresponding payload string from Messaging Return type: str
-
-
class
djmessenger.handling.
BasePostbackHandler
¶ Bases:
djmessenger.handling.BasePayloadHandler
A base class to be extended by subclass to handle custom Postback Payload
-
get_payload_string_from_messaging
(messaging)¶ Returns: The payload portion from Messaging Return type: str
-
handle
(messaging)¶
-
-
class
djmessenger.handling.
BaseQuickReplyHandler
¶ Bases:
djmessenger.handling.BasePayloadHandler
A base class to be extended by subclasses to handle custom QuickReply payload
-
get_payload_string_from_messaging
(messaging)¶
-
get_text
(messaging)¶ quick reply will come with text which is the quick reply title
Returns:
-
handle
(messaging)¶
-
-
class
djmessenger.handling.
LocationHandler
¶ Bases:
djmessenger.handling.BaseHandler
If the user sends a location to the BOT (by click on the map pin icon next to thumb up), this handler saves this coordinates to the database
-
handle
(messaging)¶
-
-
class
djmessenger.handling.
SaveMessagingHandler
¶ Bases:
djmessenger.handling.BaseHandler
This handler saves the messaging into the database for further reference
-
handle
(messaging)¶
-
-
class
djmessenger.handling.
ThumbUpHandler
¶ Bases:
djmessenger.handling.BaseHandler
Handles when the user sends a thumb up
-
handle
(messaging)¶
-
-
class
djmessenger.handling.
UserProfileHandler
¶ Bases:
djmessenger.handling.BaseHandler
Every messaging has sender.id, based on settings.DJM_SAVE_USER_PROFILE, this handler save user profile into database using models.FBUserProfile.
If DJM_SAVE_USER_PROFILE was True, we fetch user profile using graph API; otherwise we only save user psid to the database
-
handle
(messaging)¶
-
djmessenger.models module¶
Django model definition¶
-
class
djmessenger.models.
FBUserProfile
(*args, **kwargs)¶ Bases:
django.db.models.base.Model
This FBUserProfile class is to represent a user that sent a message to us via Facebook Messenger, from the message relayed by Facebook, we can look up user details which will be stored here
-
exception
DoesNotExist
¶ Bases:
django.core.exceptions.ObjectDoesNotExist
-
exception
FBUserProfile.
MultipleObjectsReturned
¶ Bases:
django.core.exceptions.MultipleObjectsReturned
-
FBUserProfile.
date_joined
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
FBUserProfile.
first_name
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
FBUserProfile.
gender
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
FBUserProfile.
get_next_by_date_joined
(*moreargs, **morekwargs)¶
-
FBUserProfile.
get_previous_by_date_joined
(*moreargs, **morekwargs)¶
-
FBUserProfile.
is_active
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
FBUserProfile.
last_name
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
FBUserProfile.
locale
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
FBUserProfile.
objects
= <django.db.models.manager.Manager object>¶
-
FBUserProfile.
profile_pic
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
FBUserProfile.
psid
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
FBUserProfile.
reply_set
¶ Accessor to the related objects manager on the reverse side of a many-to-one relation.
In the example:
class Child(Model): parent = ForeignKey(Parent, related_name='children')
parent.children
is aReverseManyToOneDescriptor
instance.Most of the implementation is delegated to a dynamically defined manager class built by
create_forward_many_to_many_manager()
defined below.
-
FBUserProfile.
thumbups
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
FBUserProfile.
timezone
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
FBUserProfile.
userlocation_set
¶ Accessor to the related objects manager on the reverse side of a many-to-one relation.
In the example:
class Child(Model): parent = ForeignKey(Parent, related_name='children')
parent.children
is aReverseManyToOneDescriptor
instance.Most of the implementation is delegated to a dynamically defined manager class built by
create_forward_many_to_many_manager()
defined below.
-
exception
-
class
djmessenger.models.
Messaging
(*args, **kwargs)¶ Bases:
django.db.models.base.Model
A table to store
djmessenger.receiving.Messaging
-
exception
DoesNotExist
¶ Bases:
django.core.exceptions.ObjectDoesNotExist
-
exception
Messaging.
MultipleObjectsReturned
¶ Bases:
django.core.exceptions.MultipleObjectsReturned
-
Messaging.
body
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
Messaging.
id
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
Messaging.
objects
= <django.db.models.manager.Manager object>¶
-
Messaging.
type
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
exception
-
class
djmessenger.models.
Reply
(*args, **kwargs)¶ Bases:
django.db.models.base.Model
A table to store all replies
-
exception
DoesNotExist
¶ Bases:
django.core.exceptions.ObjectDoesNotExist
-
exception
Reply.
MultipleObjectsReturned
¶ Bases:
django.core.exceptions.MultipleObjectsReturned
-
Reply.
data
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
Reply.
date_sent
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
Reply.
get_next_by_date_sent
(*moreargs, **morekwargs)¶
-
Reply.
get_previous_by_date_sent
(*moreargs, **morekwargs)¶
-
Reply.
id
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
Reply.
objects
= <django.db.models.manager.Manager object>¶
-
Reply.
recipient
¶ Accessor to the related object on the forward side of a many-to-one or one-to-one relation.
In the example:
class Child(Model): parent = ForeignKey(Parent, related_name='children')
child.parent
is aForwardManyToOneDescriptor
instance.
-
Reply.
recipient_id
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
Reply.
response
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
Reply.
status_code
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
Reply.
type
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
exception
-
class
djmessenger.models.
UserLocation
(*args, **kwargs)¶ Bases:
django.db.models.base.Model
From the message user sent via Facebook to us, addition to saving the raw request body into RawBody, we try to see if the sent message is actually a location that contains lat and long, if yes, then we save it here
-
exception
DoesNotExist
¶ Bases:
django.core.exceptions.ObjectDoesNotExist
-
exception
UserLocation.
MultipleObjectsReturned
¶ Bases:
django.core.exceptions.MultipleObjectsReturned
-
UserLocation.
date_created
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
UserLocation.
get_next_by_date_created
(*moreargs, **morekwargs)¶
-
UserLocation.
get_previous_by_date_created
(*moreargs, **morekwargs)¶
-
UserLocation.
id
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
UserLocation.
latitude
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
UserLocation.
longitude
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
UserLocation.
mid
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
UserLocation.
objects
= <django.db.models.manager.Manager object>¶
-
UserLocation.
seq
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
UserLocation.
timestamp
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
UserLocation.
url
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
UserLocation.
user
¶ Accessor to the related object on the forward side of a many-to-one or one-to-one relation.
In the example:
class Child(Model): parent = ForeignKey(Parent, related_name='children')
child.parent
is aForwardManyToOneDescriptor
instance.
-
UserLocation.
user_id
¶ A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
-
exception
djmessenger.payload module¶
# Payload
Payload object is being used in both handlers and senders, it starts with you, as the BOT, sends the user buttons or quick replies, each of them contains a payload.
Payload is represented in Facebook callback as a simple string, however, in order for BOT to better handle it, we are going to treat it as a valid json string.
A payload contains key-value pairs that are dependant to your business logic, as a result, you will need to write your own payload if you’d like to send buttons and replies.
Payload class provides a get_instance() classmethod that simply take a json string and try to deserialize it back to an instance of the actual subclass.
Here is a quick example, let’s say you want to display your products when the user sends you a simple text “products”, what you need to do is
Define routing policy
In your routing policy, specify SimpleTextBaseHandler and provide regex as “^products$” as a handler for SIMPLE_TEXT
Custom Sender
Write a custom sender which extends either BaseButtonSender or BaseQuickReplySender and provide payload that contains your product info, something like
> Make sure you call super().__init__()
``` class MyProductPayload(Payload):
- def __init__(self, name, price):
super().__init__() self.name = name self.price = price
when you’re sending, this payload will be serialized into a single string and sent along with the template.
- If you subclassed BaseButtonSender, you can add_button() and provide your
payload, add multiple buttons using different content in the payload to represent multiple products
- Similarly, if you subclassed BaseQuickReplySender, you can add_quick_reply()
and provide your payload instance
The main difference between buttons and quick replies are: 1. Buttons can only have 3 at a time 2. Quick Replies can have 10 at a time 3. When user clicks on Buttons, it generates a POSTBACK`` 4. When user clicks on quick replies, it generates a **QUICK_REPLY which is
a variant of a SIMPLE_TEXT
Custom handler
If you want to do something when user clicks on the buttons or quick replies (which you most likely would, otherwise why sent buttons, right), you need to implement a custom handler which extends either BaseQuickReplyHandler or BasePostbackHandler.
Both of them defines a method get_payload() which will return your an instance of MyProductPayload, at this point you know which user (PSID) clicks on which button (payload) and you can do something like saving to database
Sender
Then you can use built-in sender or custom sender again to send something back to the user
-
class
djmessenger.payload.
GetStartedPayload
¶ Bases:
djmessenger.payload.Payload
-
class
djmessenger.payload.
Payload
¶ Bases:
djmessenger.utils.serializable.Serializable
,abc.ABC
Your customized Payload subclass must extend this class and MAKE SURE that you call super().__init__ in your __init__()
-
PAYLOAD_CLASS_ATTRIBUTE
= 'payload_class'¶
-
get_class
()¶ Returns: the Payload subclass Return type: class
-
classmethod
get_instance
(json_data)¶ This class method takes either a string in json format or a dict that represents a subclass of Payload. Since all payload subclass must subclass Payload and each of them has payload_class defined, we can easily determine what is the exact payload class and load the data and return an instance of that subclass
Parameters: json_data (str or dict) – string or dict that represents the subclass of Payload Returns: an instance of the subclass of Payload Type: subclass of Payload - @raise ValueError: 1. json_data is empty
- json_data is neither str nor dict
- json_data load failed
- json_data load successfully but does not load as a dict
- loaded json_data but it doesn’t contain payload_class attribute
- unable to deserialize it back to the Payload subclass
@raise ImportError: load_class failed @raise AttributeError: load_class failed
-
is_valid
()¶ Facebook restricts that payload string can not exceed 1000 chars
Returns: True if the serialized string is less than or equal to 1000; False otherwise Return type: bool
-
-
class
djmessenger.payload.
PersistentMenuFivePayload
¶ Bases:
djmessenger.payload.Payload
-
class
djmessenger.payload.
PersistentMenuFourPayload
¶ Bases:
djmessenger.payload.Payload
-
class
djmessenger.payload.
PersistentMenuOnePayload
¶ Bases:
djmessenger.payload.Payload
-
class
djmessenger.payload.
PersistentMenuThreePayload
¶ Bases:
djmessenger.payload.Payload
-
class
djmessenger.payload.
PersistentMenuTwoPayload
¶ Bases:
djmessenger.payload.Payload
djmessenger.receiving module¶
# Receiving module
This module contains all classes that represent a Facebook callback. Basically this is just models to represent the json templates that Facebook would sent over as described here:
[Facebook Webhook Reference](https://developers.facebook.com/docs/messenger-platform/webhook-reference)
-
class
djmessenger.receiving.
AccountLinking
(status, authorization_code='')¶
-
class
djmessenger.receiving.
AccountLinkingChecker
(messaging)¶ Bases:
djmessenger.receiving.MessagingChecker
-
check
()¶
-
-
class
djmessenger.receiving.
Attachment
(ttype, payload, url)¶ Bases:
djmessenger.utils.serializable.Serializable
There are 2 types of Attachment payloads, LocationAttachmentPayload and MultimediaAttachmentPayload, so we are not providing _obj_map but need to override deserialize to look at self.type and determine which type of payload to deserialize to
-
classmethod
deserialize
(json_data)¶
-
classmethod
-
class
djmessenger.receiving.
AttachmentType
(name, description='')¶ Bases:
djmessenger.utils.serializable.SerializableEnum
-
AUDIO
= (AttachmentType) audio¶
-
FILE
= (AttachmentType) file¶
-
IMAGE
= (AttachmentType) image¶
-
LOCATION
= (AttachmentType) location¶
-
VIDEO
= (AttachmentType) video¶
-
members
= {'audio': (AttachmentType) audio, 'video': (AttachmentType) video, 'location': (AttachmentType) location, 'file': (AttachmentType) file, 'image': (AttachmentType) image}¶
-
-
class
djmessenger.receiving.
AuthenticationChecker
(messaging)¶ Bases:
djmessenger.receiving.MessagingChecker
-
check
()¶
-
-
class
djmessenger.receiving.
Callback
(object='page', entry=[])¶ Bases:
djmessenger.utils.serializable.Serializable
https://developers.facebook.com/docs/messenger-platform/webhook-reference
-
custom_obj_map
= {'entry': [<class 'djmessenger.receiving.Entry'>, <class 'list'>]}¶
-
classmethod
get_instance
(request)¶ Parameters: request (django.core.handlers.wsgi.WSGIRequest) – HTTP Request object Returns: instance of Callback Return type: Callback
-
get_sender_id
()¶ Each callback must have some Messaging, we should expect that we can always get a sender id
Returns:
-
-
class
djmessenger.receiving.
Coordinates
(lat, llong)¶
-
class
djmessenger.receiving.
Delivery
(watermark, seq, mids=[])¶
-
class
djmessenger.receiving.
Entry
(iid, time, messaging=[])¶ Bases:
djmessenger.utils.serializable.Serializable
https://developers.facebook.com/docs/messenger-platform/webhook-reference
-
custom_obj_map
= {'messaging': [<class 'djmessenger.receiving.Messaging'>, <class 'list'>]}¶
-
-
class
djmessenger.receiving.
LocationAttachmentPayload
(coordinates)¶ Bases:
djmessenger.utils.serializable.Serializable
-
custom_obj_map
= {'coordinates': [<class 'djmessenger.receiving.Coordinates'>, <class 'object'>]}¶
-
-
class
djmessenger.receiving.
Message
(text, mid, seq, sticker_id=None, quick_reply=None, attachments=[], is_echo=False, app_id='', metadata='')¶ Bases:
djmessenger.utils.serializable.Serializable
Each Messaging could have 1 Message object
-
custom_obj_map
= {'attachments': [<class 'djmessenger.receiving.Attachment'>, <class 'list'>], 'quick_reply': [<class 'djmessenger.receiving.QuickReply'>, <class 'object'>]}¶
-
-
class
djmessenger.receiving.
MessageDeliveredChecker
(messaging)¶ Bases:
djmessenger.receiving.MessagingChecker
-
check
()¶
-
-
class
djmessenger.receiving.
MessageReadChecker
(messaging)¶ Bases:
djmessenger.receiving.MessagingChecker
-
check
()¶
-
-
class
djmessenger.receiving.
MessageReceivedChecker
(messaging)¶ Bases:
djmessenger.receiving.MessagingChecker
This check handles all types in MessagedReceived and MessageEcho
-
check
()¶
-
-
class
djmessenger.receiving.
Messaging
(sender, recipient, timestamp=1478907792, message=None, postback=None, optin=None, account_linking=None, delivery=None, read=None)¶ Bases:
djmessenger.utils.serializable.Serializable
Each Entry contains multiple Messaging object, Messaging has different CallbackType, we are going to define this class so that it includes all possible objects and then when we got a json data, we just load them into the objects. After we deserialized json data into Messaging, we then determine what type of a Callback this is by looking at some fields and values using CallbackTypeChecker
-
custom_obj_map
= {'postback': [<class 'djmessenger.receiving.Postback'>, <class 'object'>], 'account_linking': [<class 'djmessenger.receiving.AccountLinking'>, <class 'object'>], 'optin': [<class 'djmessenger.receiving.Optin'>, <class 'object'>], 'message': [<class 'djmessenger.receiving.Message'>, <class 'object'>], 'sender': [<class 'djmessenger.receiving.Sender'>, <class 'object'>], 'recipient': [<class 'djmessenger.receiving.Recipient'>, <class 'object'>], 'read': [<class 'djmessenger.receiving.Read'>, <class 'object'>], 'delivery': [<class 'djmessenger.receiving.Delivery'>, <class 'object'>]}¶
-
get_coordinates
()¶ Returns: Return type: Coordinates
-
get_postback_payload
()¶ Returns: Return type: str
-
get_psid
()¶
-
get_quick_reply_payload
()¶
-
get_receiving_type
()¶ After loading the json data into this object, try to determine what type of callback this messaging is
Returns: Return type: ReceivingType
-
get_sticker_id
()¶
-
get_text
()¶ Returns: Return type: str
-
get_url
()¶ Returns: Return type: str
-
get_watermark
()¶
-
-
class
djmessenger.receiving.
MessagingChecker
(messaging)¶ Bases:
abc.ABC
MessagingChecker is to check a messaging that ReceivingType it should be
-
check
()¶ Returns: Corresponding CallbackType if it passed any check; None if nothing matches Return type: ReceivingType
-
-
class
djmessenger.receiving.
MultimediaAttachmentPayload
(url)¶
-
class
djmessenger.receiving.
Optin
(ref)¶
-
class
djmessenger.receiving.
Postback
(payload)¶
-
class
djmessenger.receiving.
PostbackReceivedChecker
(messaging)¶ Bases:
djmessenger.receiving.MessagingChecker
-
check
()¶
-
-
class
djmessenger.receiving.
QuickReply
(payload)¶
-
class
djmessenger.receiving.
Read
(watermark, seq)¶
-
class
djmessenger.receiving.
ReceivingType
(name, description='')¶ Bases:
djmessenger.utils.serializable.SerializableEnum
ReceivingType defines all types that will be sent by Facebook
-
ACCOUNT_LINKING
= (ReceivingType) ACCOUNT_LINKING¶
-
AUDIO
= (ReceivingType) AUDIO¶
-
AUTHENTICATION
= (ReceivingType) AUTHENTICATION¶
-
DEFAULT
= (ReceivingType) DEFAULT¶
-
DELIVERED
= (ReceivingType) DELIVERED¶
-
ECHO
= (ReceivingType) ECHO¶
-
FILE
= (ReceivingType) FILE¶
-
GET_STARTED_BUTTON
= (ReceivingType) GET_STARTED_BUTTON¶
-
IMAGE
= (ReceivingType) IMAGE¶
-
LOCATION
= (ReceivingType) LOCATION¶
-
PERSISTENT_MENU_FIVE
= (ReceivingType) PERSISTENT_MENU_FIVE¶
-
PERSISTENT_MENU_FOUR
= (ReceivingType) PERSISTENT_MENU_FOUR¶
-
PERSISTENT_MENU_ONE
= (ReceivingType) PERSISTENT_MENU_ONE¶
-
PERSISTENT_MENU_THREE
= (ReceivingType) PERSISTENT_MENU_THREE¶
-
PERSISTENT_MENU_TWO
= (ReceivingType) PERSISTENT_MENU_TWO¶
-
POSTBACK
= (ReceivingType) POSTBACK¶
-
QUICK_REPLY
= (ReceivingType) QUICK_REPLY¶
-
READ
= (ReceivingType) READ¶
-
SIMPLE_TEXT
= (ReceivingType) SIMPLE_TEXT¶
-
STICKER
= (ReceivingType) STICKER¶
-
VIDEO
= (ReceivingType) VIDEO¶
-
members
= {'FILE': (ReceivingType) FILE, 'PERSISTENT_MENU_FOUR': (ReceivingType) PERSISTENT_MENU_FOUR, 'ACCOUNT_LINKING': (ReceivingType) ACCOUNT_LINKING, 'AUTHENTICATION': (ReceivingType) AUTHENTICATION, 'PERSISTENT_MENU_FIVE': (ReceivingType) PERSISTENT_MENU_FIVE, 'READ': (ReceivingType) READ, 'PERSISTENT_MENU_THREE': (ReceivingType) PERSISTENT_MENU_THREE, 'DELIVERED': (ReceivingType) DELIVERED, 'SIMPLE_TEXT': (ReceivingType) SIMPLE_TEXT, 'STICKER': (ReceivingType) STICKER, 'ECHO': (ReceivingType) ECHO, 'IMAGE': (ReceivingType) IMAGE, 'QUICK_REPLY': (ReceivingType) QUICK_REPLY, 'DEFAULT': (ReceivingType) DEFAULT, 'PERSISTENT_MENU_TWO': (ReceivingType) PERSISTENT_MENU_TWO, 'POSTBACK': (ReceivingType) POSTBACK, 'AUDIO': (ReceivingType) AUDIO, 'LOCATION': (ReceivingType) LOCATION, 'VIDEO': (ReceivingType) VIDEO, 'PERSISTENT_MENU_ONE': (ReceivingType) PERSISTENT_MENU_ONE, 'GET_STARTED_BUTTON': (ReceivingType) GET_STARTED_BUTTON}¶
-
-
class
djmessenger.receiving.
Recipient
(iid)¶ Bases:
djmessenger.utils.serializable.Serializable
Your page
-
class
djmessenger.receiving.
Sender
(iid)¶ Bases:
djmessenger.utils.serializable.Serializable
In Receiving messages, Sender represents the Facebook user who sent this message to your page
djmessenger.replying module¶
Replying Module¶
Similarly, this replying module is to represent the json templates that should be used when sending something back to the user based on Facebook reference:
https://developers.facebook.com/docs/messenger-platform/send-api-reference
-
class
djmessenger.replying.
AudioReplier
(url)¶ Bases:
djmessenger.replying.MultimediaReplier
Reply an Audio from url
-
sending_type
= (ReplyingType) audio¶
-
-
class
djmessenger.replying.
BaseButtonReplier
(localized_string)¶ Bases:
djmessenger.replying.SimpleMessageReplier
Facebook restricts to have 3 buttons at a time
To reply a list of Button, you need to
- Define a subclass that extends
djmessenger.payload.Payload
, so that when user clicks on a button and another request calls back, we have a way to determine the origin by checking which subclass of Payload it has - Define a subclass that extends
BaseButtonReplier
- Define BUTTONS class variable like this
class MyButtonReplier(BaseButtonReplier): BUTTONS = { 'button 1': 'https://www.google.com', 'button 2': MyButtonPayload('button payload 2') }
The first button will open a new window that goes to the url; while the second button will trigger a postback request back which contains the payload
-
BUTTONS
= {}¶
-
class
Button
(title, url='', payload=None)¶
-
BaseButtonReplier.
LIMIT
= 3¶
-
classmethod
BaseButtonReplier.
deserialize
(json_data)¶
-
BaseButtonReplier.
get_message
(messaging)¶
-
BaseButtonReplier.
get_reply_type
()¶
- Define a subclass that extends
-
class
djmessenger.replying.
BaseQuickReplyReplier
(localized_string)¶ Bases:
djmessenger.replying.SimpleMessageReplier
Facebook restricts to have 10 quick replies at a time.
To reply a list of Quick Replies, you need to
- Define a subclass that extends
djmessenger.payload.Payload
, so that when user clicks on a QR and another request calls back, we have a way to determine the origin by checking which subclass of Payload it has - Define a subclass that extends
BaseQuickReplyReplier
- Define QUICK_REPLIES class variable like this
class MyQuickReplyReplier(BaseQuickReplyReplier): QUICK_REPLIES = { 'qr 1': MyQuickReplyPayload('qr payload 1'), 'qr 2': MyQuickReplyPayload('qr payload 2'), 'qr 3': MyQuickReplyPayload('qr payload 3'), }
-
LIMIT
= 10¶
-
QUICK_REPLIES
= {}¶
-
class
QuickReply
(title='', payload=None)¶
-
BaseQuickReplyReplier.
add_quick_reply
(title, payload)¶ An entry of quick reply button is represented like this as Facebook defined
{ "content_type":"text", "title":"Red", "payload":"DEVELOPER_DEFINED_PAYLOAD_FOR_PICKING_RED" },
content_type must be “text”, so the arguments here are title and payload , payload must be a subclass of Payload
-
classmethod
BaseQuickReplyReplier.
deserialize
(json_data)¶
-
BaseQuickReplyReplier.
get_message
(messaging)¶
-
BaseQuickReplyReplier.
get_reply_type
()¶
- Define a subclass that extends
-
class
djmessenger.replying.
ButtonType
(name, description='')¶ Bases:
djmessenger.utils.serializable.SerializableEnum
-
POSTBACK
= (ButtonType) postback¶
-
WEB_URL
= (ButtonType) web_url¶
-
members
= {'web_url': (ButtonType) web_url, 'postback': (ButtonType) postback}¶
-
-
class
djmessenger.replying.
CommonReplier
¶ Bases:
djmessenger.utils.serializable.Serializable
Base class for all repliers, 2 abstract methods need to be overridden
CommonReplier.get_message()
CommonReplier.get_reply_type()
-
get_message
(messaging)¶ Based on the attributes the class constructor constructs, this method returns the message body, the returned must be a dict and valid json object.
- When construct the request json payload, if there is any text that
- could be i18n’ed, please make sure to use
CommonReplier.preprocess_outgoing_string()
to make sure the string is using correct localeReturns: Return type: dict
-
get_reply_type
()¶ Return the SendingType that this Sender sends
Returns: Return type: ReplyingType
-
notification_type
= (NotificationType) REGULAR¶
-
static
preprocess_outgoing_string
(psid, localized_text, add_prefix=True)¶ This method take cares of any preprocessing of the outgoing text. More specifically, this method converts the text into the user’s locale, if available.
Parameters: - psid –
- localized_text (LocalizedString) –
- add_prefix (bool) – whether prepend DJM_BOT_PREFIX to the start of text, you might want to use it when processing button text
Returns: localized string
Return type: str
-
reply
(messaging)¶ Ask the replier to reply to the psid from the given messaging
-
sender_action
= None¶
-
-
class
djmessenger.replying.
DefaultMessageReplier
¶ Bases:
djmessenger.replying.SimpleMessageReplier
Sends back simple text DJM_DEFAULT_SENDER_TEXT
-
class
djmessenger.replying.
FileReplier
(url)¶ Bases:
djmessenger.replying.MultimediaReplier
Reply a File from url
-
sending_type
= (ReplyingType) file¶
-
-
class
djmessenger.replying.
ImageReplier
(url)¶ Bases:
djmessenger.replying.MultimediaReplier
Reply an Image from url
-
sending_type
= (ReplyingType) image¶
-
-
class
djmessenger.replying.
MultimediaReplier
(url)¶ Bases:
djmessenger.replying.CommonReplier
Send back multimedia from a url
ReplyingType.IMAGE = ReplyingType(‘IMAGE’) ReplyingType.AUDIO = ReplyingType(‘AUDIO’) ReplyingType.VIDEO = ReplyingType(‘VIDEO’) ReplyingType.FILE = ReplyingType(‘FILE’)
-
get_message
(messaging)¶
-
get_reply_type
()¶
-
sending_type
= None¶
-
-
class
djmessenger.replying.
NotificationType
(name, description='')¶ Bases:
djmessenger.utils.serializable.SerializableEnum
-
NO_PUSH
= (NotificationType) NO_PUSH¶
-
REGULAR
= (NotificationType) REGULAR¶
-
SILEN_PUSH
= (NotificationType) SILEN_PUSH¶
-
members
= {'NO_PUSH': (NotificationType) NO_PUSH, 'REGULAR': (NotificationType) REGULAR, 'SILEN_PUSH': (NotificationType) SILEN_PUSH}¶
-
-
class
djmessenger.replying.
ReplyAction
(name, description='')¶ Bases:
djmessenger.utils.serializable.SerializableEnum
-
MARK_SEEN
= (ReplyAction) mark_seen¶
-
TYPING_OFF
= (ReplyAction) typing_off¶
-
TYPING_ON
= (ReplyAction) typing_on¶
-
members
= {'typing_off': (ReplyAction) typing_off, 'mark_seen': (ReplyAction) mark_seen, 'typing_on': (ReplyAction) typing_on}¶
-
-
class
djmessenger.replying.
ReplyActionReplier
(action)¶ Bases:
djmessenger.replying.CommonReplier
Send a ReplyAction
-
get_message
(messaging)¶
-
get_reply_type
()¶
-
-
class
djmessenger.replying.
ReplyingType
(name, description='')¶ Bases:
djmessenger.utils.serializable.SerializableEnum
-
AUDIO
= (ReplyingType) audio¶
-
BUTTON
= (ReplyingType) button¶
-
FILE
= (ReplyingType) file¶
-
IMAGE
= (ReplyingType) image¶
-
QUICK_REPLY
= (ReplyingType) quick_reply¶
-
SENDER_ACTION
= (ReplyingType) sender_action¶
-
SIMPLE_TEXT
= (ReplyingType) simple_text¶
-
VIDEO
= (ReplyingType) video¶
-
members
= {'sender_action': (ReplyingType) sender_action, 'video': (ReplyingType) video, 'file': (ReplyingType) file, 'button': (ReplyingType) button, 'audio': (ReplyingType) audio, 'simple_text': (ReplyingType) simple_text, 'quick_reply': (ReplyingType) quick_reply, 'image': (ReplyingType) image}¶
-
-
class
djmessenger.replying.
SimpleMessageReplier
(localized_string)¶ Bases:
djmessenger.replying.CommonReplier
Send a simple text message
-
custom_obj_map
= {'localized_string': (<class 'djmessenger.utils.utils.LocalizedString'>, <class 'object'>)}¶
-
get_message
(messaging)¶
-
get_reply_type
()¶
-
-
class
djmessenger.replying.
VideoReplier
(url)¶ Bases:
djmessenger.replying.MultimediaReplier
Reply a Video from url
-
sending_type
= (ReplyingType) video¶
-
djmessenger.routing module¶
In a nutshell, the overall flow works like this
- receiving module converts incoming request body to a Callback instance
- Each Callback instance contains multiple Entry and each Entry contains multiple Messaging
- For each Messaging, we are going to apply this routing policy
Each routing policy contains
A list of Rule
A rule contains a list of filters, a list of handlers and a list of repliers
- 2.1 filters are responsible for determining whether the given Messaging
is applicable for further handling, a Messaging object must pass all listed filters in order to reach handlers
- 2.2 handlers perform internal operations against the Messaging, such like
saving something into database and etc
2.3 repliers reply something back to the user
See djmessenger.utils.default_routing_policy
for sample routing policy
and more details
-
class
djmessenger.routing.
Policy
(rules=[])¶ Bases:
djmessenger.utils.serializable.Serializable
A
Policy
is the most important component in djmessenger. A Policy defines multipleRule
and when we got message from customer, we simplyPolicy.apply()
the message-
apply
(messaging)¶ Apply this Policy to the given messaging instance
Parameters: messaging (djmessenger.receiving.Messaging) – An instance of Messaging class
-
custom_obj_map
= {'rules': [<class 'djmessenger.routing.Rule'>, <class 'list'>]}¶
-
get_default_rule
()¶ There can only be 1 Rule that has type DEFAULT, if there were multiple, return the first one; return empty list if not found.
The filters, handlers and repliers defined in DEFAULT Rule will be applied on all Rules
-
classmethod
get_instance
(json_data)¶ Given a json string, deserialize it and return a
Policy
Returns: Policy Return type: Policy
-
get_rules
(rtype)¶
-
-
class
djmessenger.routing.
Rule
(ttype, name='', filters=[], handlers=[], repliers=[])¶ Bases:
djmessenger.utils.serializable.Serializable
A
Rule
is a class that will be applied to aMessaging
instance. EachRule
contains a list of filters, a list of handlers and a list of repliers.Filters take a
Messaging
and determine whether thisMessaging
should proceed further, if any of the Filters returns False, thisRule
will be skipped.See
djmessenger.utils.default_routing_policy
for sample routing policy and more details-
custom_obj_map
= {'repliers': [<class 'djmessenger.routing.TargetReplierClass'>, <class 'list'>], 'handlers': [<class 'djmessenger.routing.TargetHandlerClass'>, <class 'list'>], 'filters': [<class 'djmessenger.routing.TargetFilterClass'>, <class 'list'>]}¶
-
get_filter_instances
()¶
-
get_filter_wrappers
()¶ Returns: A list of TargetFilterClass instances which is a wrapper for BaseFilter
-
get_handler_instances
()¶
-
get_handler_wrappers
()¶ Returns: A list of TargetHandlerClass instances which is a wrapper for BaseHandler
-
get_receiving_type
()¶ Each
Rule
defines adjmessenger.receiving.ReceivingType
, this method returns itReturn type: ReceivingType
-
get_replier_instances
()¶
-
get_replier_wrappers
()¶ Returns: A list of TargetReplierClass instances which is a wrapper for CommonReplier
-
-
class
djmessenger.routing.
TargetClass
(name, args={})¶ Bases:
djmessenger.utils.serializable.Serializable
This class is a wrapper for filter, handler and replier which were defined in the policy file. When we are reading the policy file, we will first deserialize each dict using this class and this class is responsible for determining the exact target class and return an instance of it
-
BASE_CLASS
= None¶
-
get_args
()¶
-
get_class
()¶ Loads and return the exact class from
self.name
Returns: A class Return type: class
-
get_instance
()¶ Return an instance of the target class, which will be an instance of subclass of either
djmessenger.filtering.BaseFilter
,djmessenger.handling.BaseHandler
ordjmessenger.replying.CommonReplier
Return type: object
-
-
class
djmessenger.routing.
TargetFilterClass
(name, args={})¶ Bases:
djmessenger.routing.TargetClass
-
BASE_CLASS
¶ alias of
BaseFilter
-
-
class
djmessenger.routing.
TargetHandlerClass
(name, args={})¶ Bases:
djmessenger.routing.TargetClass
-
BASE_CLASS
¶ alias of
BaseHandler
-
-
class
djmessenger.routing.
TargetReplierClass
(name, args={})¶ Bases:
djmessenger.routing.TargetClass
-
BASE_CLASS
¶ alias of
CommonReplier
-
djmessenger.settings module¶
-
djmessenger.settings.
DJM_BOT_PREFIX
= <django.utils.functional.lazy.<locals>.__proxy__ object>¶ Prefix this string to all text messages sent to users
-
djmessenger.settings.
DJM_BUSINESS_ADDRESS
= ''¶ This address is where your business is located at
-
djmessenger.settings.
DJM_DEFAULT_SENDER_TEXT
= 'Thanks for your message'¶ A sender named djmessenger.sending.DefaultSender which is a SimpleTextSender you can define your message here and directly use it in DJM_ROUTING_POLICY
-
djmessenger.settings.
DJM_ENDPOINT
= 'aef40e8e2b258e647fe84655eab910a7a70bc0031e382f01ba'¶ The endpoint that Facebook will relay the callback message to also being used to setup webhook
-
djmessenger.settings.
DJM_ENDPOINT_VERIFY_TOKEN
= 'djmessenger_verify_token'¶ Verify Token to be used when verifying endpoint in developer.facebook.com
-
djmessenger.settings.
DJM_PAGE_ACCESS_TOKEN
= 'EAABtMkLqTLoBANwSkJxgqhkDtZBD9QLlzT4YW8JvxvzauC7nkaTtNRkqetF32mcTuwfQjtpm1cmZBx8HttEYLJ3MFDjeg8SLf6ZA6o84V0540McEEYHuoi7MZBHmAxvT08Kq5Iizj3uD0KqZCfUEGqwId4v5gAvXvifd7mw5TRQZDZD'¶ Facebook Page Access Token, get it from developers.facebook.com
-
djmessenger.settings.
DJM_ROUTING_POLICY
= {'rules': [{'name': 'default rule', 'type': 'DEFAULT', 'handlers': [{'name': 'djmessenger.handling.UserProfileHandler'}, {'name': 'djmessenger.handling.SaveMessagingHandler'}], 'filters': [{'args': {'end_time': '2017-1-1T01:00:00Z-0800', 'start_time': '2016-1-1T00:00:00Z-0800'}, 'name': 'djmessenger.filtering.TimeFilter'}]}, {'name': 'ThumbUp Rule', 'type': 'STICKER', 'repliers': [{'args': {'localized_string': {'translations': {'zh_TW': '謝謝您的讚'}, 'base_string': 'Thank you for your thumb!!!'}}, 'name': 'djmessenger.replying.SimpleMessageReplier'}, {'args': {'url': 'https://dl.dropboxusercontent.com/u/717667/icons/betatesting.png'}, 'name': 'djmessenger.replying.ImageReplier'}], 'handlers': [{'name': 'djmessenger.handling.ThumbUpHandler'}], 'filters': [{'name': 'djmessenger.filtering.ThumbUpFilter'}]}, {'name': 'Hello Chinese Rule', 'type': 'SIMPLE_TEXT', 'repliers': [{'args': {'localized_string': {'translations': {'en_US': 'Hello to you, too!'}, 'base_string': '您也好'}}, 'name': 'djmessenger.replying.SimpleMessageReplier'}], 'filters': [{'args': {'regex': '^你好$'}, 'name': 'djmessenger.filtering.SimpleTextRegexFilter'}]}, {'name': 'Hi Rule', 'type': 'SIMPLE_TEXT', 'repliers': [{'args': {'localized_string': {'translations': {'zh_TW': '您也好'}, 'base_string': 'Hi you, too!'}}, 'name': 'djmessenger.replying.SimpleMessageReplier'}], 'filters': [{'args': {'regex': '^hi$'}, 'name': 'djmessenger.filtering.SimpleTextRegexFilter'}]}, {'name': 'buttons Rule', 'type': 'SIMPLE_TEXT', 'repliers': [{'args': {'localized_string': {'translations': {'zh_TW': '請選擇一個按鈕'}, 'base_string': 'Please choose a button'}}, 'name': 'testapp.sending.MyButtonSender'}], 'filters': [{'args': {'regex': '^buttons$'}, 'name': 'djmessenger.filtering.SimpleTextRegexFilter'}]}, {'name': 'Location Rule', 'type': 'LOCATION', 'handlers': [{'name': 'djmessenger.handling.LocationHandler'}], 'filters': [{'name': 'djmessenger.filtering.LocationFilter'}]}, {'name': 'PM1 Rule', 'type': 'PERSISTENT_MENU_ONE', 'repliers': [{'args': {'localized_string': {'translations': {'zh_TW': '這是幫助訊息'}, 'base_string': 'This is help info'}}, 'name': 'djmessenger.replying.SimpleMessageReplier'}, {'args': {'localized_string': {'translations': {'zh_TW': '請選擇快速回覆'}, 'base_string': 'Please choose a QR'}}, 'name': 'testapp.sending.MyQuickReplySender'}]}, {'name': 'QR1 Rule', 'type': 'QUICK_REPLY', 'repliers': [{'args': {'localized_string': {'translations': {'zh_TW': '謝謝您的快速回覆'}, 'base_string': 'Thanks for the quick reply'}}, 'name': 'djmessenger.replying.SimpleMessageReplier'}], 'handlers': [{'name': 'testapp.handling.MyQuickReplyHandler'}]}]}¶ DJM_ROUTING_POLICY defines the lifecycle of a message being received, handling it and lastly send some response back. In the following format, each router represents a type of message received, handlers represent which handlers should be used to handle this type of message and lastly which senders should be used to send the response back.
See
djmessenger.utils.default_routing_policy
for more details
-
djmessenger.settings.
DJM_SAVE_USER_PROFILE
= True¶ Whether DJM should automatically fetch and save user profile for any user that sends message to the page and observed by BOT, default to True
-
djmessenger.settings.
DJM_THREAD_ENABLE_AUTO_CONFIG
= False¶ If set to True, djmessenger will send POST request to configure thread automatically. If set to False, you need to configure it by using management commands
-
djmessenger.settings.
DJM_THREAD_ENABLE_GET_STARTED_BUTTON
= True¶ https://developers.facebook.com/docs/messenger-platform/thread-settings/get-started-button Whether to enable get started button feature
-
djmessenger.settings.
DJM_THREAD_GREETINGS_TEXT
= <django.utils.functional.lazy.<locals>.__proxy__ object>¶ https://developers.facebook.com/docs/messenger-platform/thread-settings/greeting-text
- length must be <= 160
- only first time visitor sees this greeting text
djmessenger.urls module¶
djmessenger URL Configuration
- The urlpatterns list routes URLs to views. For more information please see:
- https://docs.djangoproject.com/en/1.9/topics/http/urls/
Examples: Function views
- Add an import: from my_app import views
- Add a URL to urlpatterns: url(r’^$’, views.home, name=’home’)
- Class-based views
- Add an import: from other_app.views import Home
- Add a URL to urlpatterns: url(r’^$’, Home.as_view(), name=’home’)
- Including another URLconf
- Import the include() function: from django.conf.urls import url, include
- Add a URL to urlpatterns: url(r’^blog/’, include(‘blog.urls’))
djmessenger.views module¶
Module contents¶
-
djmessenger.
get_git_changeset
()¶ Returns a numeric identifier of the latest git changeset. The result is the UTC timestamp of the changeset in YYYYMMDDHHMMSS format. This value isn’t guaranteed to be unique, but collisions are very unlikely, so it’s sufficient for generating the development version numbers. TODO: Check if we can rely on services like read-the-docs to pick this up.
-
djmessenger.
get_version
(version=None)¶ Returns a PEP 386-compliant version number from VERSION.