Skip to content

Instantly share code, notes, and snippets.

@fffonion
Created April 23, 2014 10:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fffonion/11210337 to your computer and use it in GitHub Desktop.
Save fffonion/11210337 to your computer and use it in GitHub Desktop.
SAE internal apis
#!/usr/bin/env python
# -*-coding: utf8 -*-
"""Channel API
"""
import time
import json
import urllib
import urllib2
from urlparse import urlparse
import socket
from httplib import HTTPConnection, HTTPException
from core import retry
MAXIMUM_CLIENT_ID_LENGTH = 118
MAXIMUM_TOKEN_DURATION_SECONDS = 24 * 60
MAXIMUM_MESSAGE_LENGTH = 32767
class Error(Exception):
"""Base error class for this module."""
class InvalidChannelClientIdError(Error):
"""Error that indicates a bad client id."""
class InvalidChannelTokenDurationError(Error):
"""Error that indicates the requested duration is invalid."""
class InvalidMessageError(Error):
"""Error that indicates a message is malformed."""
class InternalError(Error):
"""Error that indicates server side error"""
def _to_channel_error(res):
error_map = {
1: InvalidChannelClientIdError,
2: InvalidMessageError,
}
return error_map.get(res['errno']) or Error(res)
def _validate_client_id(client_id):
if not isinstance(client_id, basestring):
raise InvalidChannelClientIdError('"%s" is not a string.' % client_id)
if isinstance(client_id, unicode):
client_id = client_id.encode('utf-8')
if len(client_id) > MAXIMUM_CLIENT_ID_LENGTH:
msg = 'Client id length %d is greater than max length %d' % (
len(client_id), MAXIMUM_CLIENT_ID_LENGTH)
raise InvalidChannelClientIdError(msg)
return client_id
_BACKEND = urlparse('http://channel.sae.sina.com.cn/v1/')
@retry(InternalError)
def _remote_call(op, **args):
payload = urllib.urlencode(args)
try:
c = HTTPConnection(_BACKEND.netloc, timeout=10)
c.request('POST', _BACKEND.path + op, payload,
{'content-type': 'application/x-www-form-urlencoded'})
rep = c.getresponse()
if rep.status == 200:
body = rep.read()
else:
raise InternalError()
except (HTTPException, socket.error):
raise InternalError()
try:
rc = json.loads(body)
except TypeError:
raise InternalError()
if 'error' in rc:
raise Error(rc['error'])
if rc.has_key('data'):
return rc['data']
def create_channel(name, duration=None):
client_id = _validate_client_id(name)
if duration is not None:
if not isinstance(duration, (int, long)):
raise InvalidChannelTokenDurationError(
'Argument duration must be integral')
elif duration < 1:
raise InvalidChannelTokenDurationError(
'Argument duration must not be less than 1')
elif duration > MAXIMUM_TOKEN_DURATION_SECONDS:
msg = ('Argument duration must be less than %d'
% (MAXIMUM_TOKEN_DURATION_SECONDS + 1))
raise InvalidChannelTokenDurationError(msg)
return _remote_call('create_channel',
client_id=client_id, duration=duration)
def send_message(name, message):
client_id = name
if isinstance(message, unicode):
message = message.encode('utf-8')
elif not isinstance(message, str):
raise InvalidMessageError('Message must be a string')
if len(message) > MAXIMUM_MESSAGE_LENGTH:
raise InvalidMessageError(
'Message must be no longer than %d chars' % MAXIMUM_MESSAGE_LENGTH)
return _remote_call('send_message', client_id=client_id, message=message)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment