Skip to content

Instantly share code, notes, and snippets.

@etowett
Created November 8, 2016 09:46
Show Gist options
  • Save etowett/2dc1bacb221b8894554916665f78b384 to your computer and use it in GitHub Desktop.
Save etowett/2dc1bacb221b8894554916665f78b384 to your computer and use it in GitHub Desktop.
These two files demonstrate how to send SMSes using AfricasTalking API (https://africastalking.com/) in an asynchronous way.
#!/usr/bin/python2.7
import urllib
from twisted.internet import protocol
from twisted.internet import defer
from twisted.web.http_headers import Headers
from twisted.internet import reactor
from twisted.web.client import Agent
from twisted.web.iweb import IBodyProducer
from zope.interface import implements
from twisted.internet.defer import succeed
class StringProducer(object):
implements(IBodyProducer)
def __init__(self, body):
self.body = body
self.length = len(body)
def startProducing(self, consumer):
consumer.write(self.body)
return succeed(None)
def pauseProducing(self):
pass
def stopProducing(self):
pass
class SimpleReceiver(protocol.Protocol):
def __init__(self, d):
self.buf = ''
self.d = d
def dataReceived(self, data):
self.buf += data
def connectionLost(self, reason):
self.d.callback(self.buf)
def http_request(url, values=None, method='POST', headers=None, pool=None):
from twisted.web import client
client._HTTP11ClientFactory.noisy = False
agent = Agent(reactor, pool=pool)
data = urllib.urlencode(values) if values else None
d = agent.request(
method, url, Headers(headers) if headers else {},
StringProducer(data) if data else None
)
def handle_response(response):
if response.code == 204:
d = defer.succeed('')
else:
d = defer.Deferred()
response.deliverBody(SimpleReceiver(d))
return d
d.addCallback(handle_response)
return d
#!/usr/bin/python2.7
import json
from httpreq import http_request
from twisted.internet import defer, reactor
from twisted.web.client import HTTPConnectionPool
pool = HTTPConnectionPool(reactor)
SEMA = None
def get_semaphore():
"""Limit number of concurrent operarions."""
global SEMA
if SEMA is None:
SEMA = defer.DeferredSemaphore(150)
return SEMA
sem = get_semaphore()
class Gateway:
"""Send message to AfricasTalking API asynchronously."""
def __init__(self, uname, key):
self.username = uname
self.key = key
self.url = "http://api.africastalking.com/version1/messaging"
self.headers = {
'Accept': ['application/json'], 'apikey': [key],
'Content-Type': ['application/x-www-form-urlencoded'],
}
self.HTTP_RESPONSE_OK = 201
self.debug = True
def send_message(self, to, message, sid=None, sms_mode=1,
enqueue=0, keyword=None, link_id=None,
retry_hrs=None):
payload = {
'username': self.username, 'to': to,
'message': message, 'bulkSMSMode': sms_mode}
if sid is not None:
payload["from"] = sid
if enqueue > 0:
payload["enqueue"] = enqueue
if keyword is not None:
payload["keyword"] = keyword
if link_id is not None:
payload["linkId"] = link_id
if retry_hrs is not None:
payload["retryDurationInHours"] = retry_hrs
d = sem.run(
http_request, self.url, payload, 'POST', self.headers, pool)
d.addCallback(self._req_success)
d.addErrback(self._req_failure)
return d
def _req_success(self, response):
if self.debug:
print "API: %s" % (response,)
return json.loads(response)
def _req_failure(self, error):
if self.debug:
print "Error on gateway: %s" % (error,)
return 'Error on API'
def main():
"""Main method."""
gw = Gateway('username', 'key')
d = gw.send_message('0727372285', 'hello world')
d.addCallback(send_success)
d.addErrback(send_failed)
return d
def send_success(result):
print "Message sent successfully.\n Response: %s" % (result,)
return
def send_failed(error):
print "Error sending message: %s" % (error,)
return
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment