Skip to content

Instantly share code, notes, and snippets.

@maracuja
Last active August 29, 2015 14:26
Show Gist options
  • Save maracuja/b2025277f7e370c862ea to your computer and use it in GitHub Desktop.
Save maracuja/b2025277f7e370c862ea to your computer and use it in GitHub Desktop.
Device Deletion and Synchronisation Code
'''
Runs when a device is deleted in the Skylark API. delete
'''
def sync_deletion(sender, instance, *args, **kwargs):
try:
if instance.removed:
delete_device(instance)
'''
when synching with ooyala we send a hash of the user id because that's
what we use on the front end.
'''
user = instance.customer.user
queued_sync_devices.delay(user)
except:
pass
'''
Send a sync_devices call to the queue
'''
def queued_sync_devices(user):
sync_devices(user)
return True
def sync_devices(user):
logging.info('-- calling sync_devices -----------------------------------')
"""
when synching with ooyala we send a hash of the user id because that's
what we use on the front end.
"""
Customer = swapper.load_model('box_office', 'Customer')
mDevice = get_model_class(label='ooyala', model='device')
mAccount = get_model_class(label='ooyala', model='account')
customer = Customer.objects.get(user__id=user.id)
user_hash = get_user_hash(customer)
account = get_default_account()
try:
api = OoyalaAPI(account.api_key, settings.OOYALA_SECRETS[account.slug], OOYALA_ENDPOINT)
devices = api.get('device_management/pcode/%s/account_id/%s/devices' % (account.pcode, user_hash,))
except:
logging.info('failed to retrieve devices from ooyala')
return None
if devices and 'devices' in devices:
for device in devices['devices']:
try:
db_device = mDevice.objects.get(public_id=device['public_device_id'])
except:
db_device = mDevice()
db_device.public_id = device['public_device_id']
db_device.user_agent = device['user_agent']
if device['nickname']:
db_device.nickname = device['nickname']
else:
db_device.nickname = ''
db_device.registered = datetime.strptime(device['registration_time'], '%Y-%m-%d %H:%M:%S +0000')
db_device.customer = customer
db_device.save()
else:
logging.info('no devices found for %s' % user_hash)
def delete_device(device):
logging.info('-- calling delete_device ----------------------------------------------------------------------')
try:
"""
when synching with ooyala we send a hash of the user id because that's
what we use on the front end.
"""
user_hash = get_user_hash(device.customer)
account = get_default_account()
api = OoyalaAPI(account.api_key, settings.OOYALA_SECRETS[account.slug], OOYALA_ENDPOINT)
api.delete('device_management/pcode/%s/account_id/%s/devices/%s' % (account.pcode, user_hash, device.public_id,))
logging.info('deleted from ooyala: %s' % device)
except:
logging.info('not deleted from ooyala')
import hashlib, base64, urllib, httplib, time, logging, json, sha
from datetime import datetime
from skylark.utils.utils import get_model_class, get_user_hash
from django.conf import settings
import swapper
HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
DEFAULT_EXPIRATION_WINDOW = 1800
DEFAULT_ROUND_UP_TIME = 300
API_VERSION = 'v2'
DEFAULT_BASE_URL = 'rl.ooyala.com'
DEFAULT_CACHE_BASE_URL = 'rl.ooyala.com'
OOYALA_ENDPOINT = 'rl.ooyala.com'
logging.basicConfig(format='',level=logging.INFO)
class OoyalaAPI(object):
def __init__(self, api_key, secret_key, base_url=DEFAULT_BASE_URL,
cache_base_url=DEFAULT_CACHE_BASE_URL,
expiration=DEFAULT_EXPIRATION_WINDOW):
"""OoyalaAPI Constructor
Type signature:
(str, str, str:DEFAULT_BASE_URL, int:DEFAULT_EXPIRATION_WINDOW) -> OoyalaAPI
Parameters:
api_key - The API key
secret_key - The secret key
base_url - the url's base
expiration - the expiration window, in seconds
Example:
api = OoyalaAPI("..", "..")
"""
self._secret_key = secret_key
self._api_key = api_key
self._base_url = base_url
self._cache_base_url = cache_base_url
self._expiration_window = expiration
self._response_headers = [()]
def send_request(self, http_method, relative_path, body=None, params={}):
"""Send a request.
Type signature:
(str, str, str:None, dict:{}) -> json str | None
Parameters:
http_method - the http method
relative_path - the url's relative path
body - the request's body
params - the query parameters
Example:
api = OoyalaAPI(secret_key, api_key)
response = api.send_request('GET', 'players/2kj390')
response = api.send_request('PATCH', 'players/2kj390', "{'name': 'my new player name'}")
"""
# create the url
if relative_path[:17] == 'device_management':
path = '/%s' % relative_path
else:
path = '/%s/%s' % (API_VERSION,relative_path,)
# Convert the body to JSON format
json_body = ''
if (body is not None):
json_body = json.dumps(body) if type(body) is not str else body
url = self.build_path_with_authentication_params(http_method, path, params, json_body)
if url is None:
return None
if relative_path[:17] == 'device_management':
base_url = self.base_url
else:
base_url = self.base_url if http_method != 'GET' else self.cache_base_url
connection = httplib.HTTPSConnection(base_url)
#hack needed when a PUT request has an empty body
headers = {}
if (body is None):
headers['Content-length'] = 0
#Make the request
connection.request(http_method, url, json_body, headers)
#get the response
response = connection.getresponse()
# import pdb;pdb.set_trace()
data = response.read()
self._response_headers = response.getheaders()
connection.close()
if (response.status >= httplib.BAD_REQUEST):
return None
else:
if (len(data)==0):
data = "true"
return json.loads(data)
def get(self, path, query={}):
"""Send a GET request.
Type signature:
(str, srt:{}) -> json str | None
Parameters:
path - the url's path
query - the query parameters
Example:
api = Ooyala(...)
response = api.get('players/2kj390')
"""
return self.send_request('GET', path, None, query)
def put(self, path, body):
"""Send a PUT request.
Type signature:
(str, object) -> json str | None
Parameters:
path - the url's path
body - the request's body
Example:
api = Ooyala(...)
response = api.put('players/2kj390/metadata', {'skin' : 'branded'})
"""
return self.send_request('PUT', path, body)
def post(self, path, body):
"""Send a POST request.
Type signature:
(str, object) -> json str | None
Parameters:
path - the url's path
body - the request's body
Example:
api = Ooyala(...)
response = api.post('players/', {'name' : 'sample player'})
"""
return self.send_request('POST', path, body)
def patch(self, path, body):
"""Send a PATCH request.
Type signature:
(str, object) -> json str | None
Parameters:
path - the url's path
body - the request's body
Example:
api = Ooyala(...)
response = api.patch('players/2kj390', {'name' : 'renamed player'})
"""
return self.send_request('PATCH', path, body)
def delete(self, path):
"""Send a DELETE request.
Type signature:
(str) -> json str | None
Key Parameters:
'path' - the url's path
Example:
api = Ooyala(...)
response = api.delete('players/2kj390')
"""
return self.send_request('DELETE', path)
def generate_signature(self, http_method, path, params, body=''):
"""Generates the signature for a request.
Type signature:
(str, str, dict, str:'') -> str
Parameters:
http_method - the http method
path - the url's path
body - the request's body (a JSON encoded string)
params - query parameters
"""
signature = str(self.secret_key) + http_method.upper() + path
for key, value in sorted(params.iteritems()):
signature += key + '=' + str(value)
# This is neccesary on python 2.7. if missing,
# signature+=body with raise an exception when body are bytes (image data)
signature = signature.encode('ascii')
signature += body
signature = base64.b64encode(hashlib.sha256(signature).digest())[0:43]
signature = urllib.quote_plus(signature)
return signature
def build_path(self, path, params):
"""Build the path for a request.
Type signature:
(str, dict) -> str
Parameters:
path - the url's path
params - the query parameters
"""
# a local function which check if item is a query param
f = lambda k: k == 'where' or k == 'orderby' or k == 'limit' or k == 'page_token'
url = path + '?'
url += "&".join(["%s=%s" % (key, urllib.quote_plus(str(value)) if f(key) else value) for key, value in params.items()])
return url
def build_path_with_authentication_params(self, http_method, path, params, body):
"""Build the path for a Ooyala API request, including authentication parameters.
Type signature:
(str, str, str, dict, str) -> str
Parameters:
http_method - the http method
path - the url's path
params - the query parameters
body - the request's body
"""
if (http_method not in HTTP_METHODS) or (self.api_key is None) or (self.secret_key is None):
return None
authentication_params = dict(params)
#add the ooyala authentication params
authentication_params['api_key'] = str(self.api_key)
authentication_params['expires'] = str(self.expires)
authentication_params['signature'] = self.generate_signature(http_method, path, authentication_params, body)
return self.build_path(path, authentication_params)
@property
def response_headers(self):
"""Get the response's header from last request made.
Type signature:
() -> [(header,value)]
"""
return self._response_headers
def get_secret_key(self):
"""Secret Key getter.
Type signature:
() -> str
Example:
api = OoyalaAPI(...)
print 'the secret key is ', api.secret_key
"""
return self._secret_key
def set_secret_key(self, value):
"""Secret Key setter.
Type signature:
(str) -> None
Parameters:
value - the secret key to be set
Example:
api = OoyalaAPI(...)
api.secret_key = "83jja"
print 'the new secret key is ', api.secret_key
"""
self._secret_key = value
secret_key = property(get_secret_key, set_secret_key)
def get_api_key(self):
"""API Key getter.
Type signature:
() -> str
Example:
api = OoyalaAPI(...)
print 'the API key is ', api.api_key
"""
return self._api_key
def set_api_key(self, value):
"""API Key setter.
Type signature:
(str) -> None
Parameters:
value - the API key to be set
Example:
api = OoyalaAPI(...)
api.api_key = "332kka"
print 'the new API key is ', api.api_key
"""
self._api_key = value
api_key = property(get_api_key, set_api_key)
def get_base_url(self):
"""Base url getter.
Type signature:
() -> str
Example:
api = OoyalaAPI(...)
print 'the base url is ', api.base_url
"""
return self._base_url
def set_base_url(self, value):
"""Base url setter.
Type signature:
(str) -> None
Parameters:
value - the url's base to be set
Example:
api = OoyalaAPI(...)
api.base_url = "cache.api.ooyala.com"
print 'the new url's base is ', api.base_url
"""
self._base_url = value
base_url = property(get_base_url, set_base_url)
def get_cache_base_url(self):
"""Cache base url getter.
Type signature:
() -> str
Example:
api = OoyalaAPI(...)
print 'the cache base url is ', api.cache_base_url
"""
return self._cache_base_url
def set_cache_base_url(self, value):
"""Cache base url setter.
Type signature:
(str) -> None
Parameters:
value - the url's base to be set
Example:
api = OoyalaAPI(...)
api.base_url = "cache.api.ooyala.com"
print 'the new url's base is ', api.cache_base_url
"""
self._cache_base_url = value
cache_base_url = property(get_cache_base_url, set_cache_base_url)
def get_expiration_window(self): return self._expiration_window
def set_expiration_window(self, value): self._expiration_window = value
def del_expiration_window(self): del self._expiration_window
expiration_window = property(get_expiration_window, set_expiration_window, del_expiration_window)
@property
def expires(self):
"""Computes the expiration's time
Type signature:
() -> int
"""
now_plus_window = int(time.time()) + self.expiration_window
return now_plus_window + DEFAULT_ROUND_UP_TIME - (now_plus_window % DEFAULT_ROUND_UP_TIME)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment