Created
April 23, 2014 10:40
-
-
Save fffonion/11210337 to your computer and use it in GitHub Desktop.
SAE internal apis
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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