Skip to content

Commit

Permalink
0.7.5
Browse files Browse the repository at this point in the history
Pubnub 4.x
Platform events
  • Loading branch information
kirill-konshin committed Feb 7, 2017
1 parent 2d721dd commit e5c8b34
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 67 deletions.
4 changes: 3 additions & 1 deletion .travis.yml
@@ -1,6 +1,7 @@
language: python
python:
- '2.7'
- 2.7
- 3.6
install:
- make install
- make install-dev
Expand All @@ -15,6 +16,7 @@ deploy:
password:
secure: L+GM30lUbOih41dAXh0fD4d3L0pcYtnvLVL9XRM2TnXJvGhh1o/jcxbMilTH8PxyMRvan+52spoJn1zZHVuzTMfrtsENT60VsvV+1nyvev07w0JaaS1OBlgeiOVTJIk7O7+/B6Jeu48e/tZMX22cdw28/WK5gMUwnPycZIMyKG4=
on:
python: 2.7
tags: true
repo: ringcentral/ringcentral-python
branch: master
3 changes: 2 additions & 1 deletion requirements.txt
@@ -1,3 +1,4 @@
observable>=0.3.1
pubnub==3.*
pubnub==4.*
pycryptodome>=3.4.4
requests>=2.12.4
14 changes: 14 additions & 0 deletions ringcentral/platform/events.py
@@ -0,0 +1,14 @@
#!/usr/bin/env python
# encoding: utf-8


class Events:
refreshSuccess = 'refreshSuccess'
refreshError = 'refreshError'
loginSuccess = 'loginSuccess'
loginError = 'loginError'
logoutSuccess = 'logoutSuccess'
logoutError = 'logoutError'

def __init__(self):
pass
79 changes: 46 additions & 33 deletions ringcentral/platform/platform.py
Expand Up @@ -2,7 +2,9 @@
# encoding: utf-8

import sys
from observable import Observable
from .auth import Auth
from .events import Events
from ..core import base64encode

ACCOUNT_ID = '~'
Expand All @@ -15,8 +17,11 @@
REFRESH_TOKEN_TTL = 604800 # 1 week


class Platform:
class Platform(Observable):
def __init__(self, client, key='', secret='', server='', name='', version=''):

Observable.__init__(self)

self._server = server
self._key = key
self._name = name if name else 'Unnamed'
Expand Down Expand Up @@ -63,42 +68,50 @@ def logged_in(self):
return False

def login(self, username, extension, password):
response = self._request_token(TOKEN_ENDPOINT, body={
'grant_type': 'password',
'username': username,
'extension': extension,
'password': password,
'access_token_ttl': ACCESS_TOKEN_TTL,
'refresh_token_ttl': REFRESH_TOKEN_TTL
})
self._auth.set_data(response.json_dict())
# TODO Add event trigger
return response
try:
response = self._request_token(TOKEN_ENDPOINT, body={
'grant_type': 'password',
'username': username,
'extension': extension,
'password': password,
'access_token_ttl': ACCESS_TOKEN_TTL,
'refresh_token_ttl': REFRESH_TOKEN_TTL
})
self._auth.set_data(response.json_dict())
self.trigger(Events.loginSuccess, response)
return response
except Exception as e:
self.trigger(Events.loginError, e)
raise e

def refresh(self):
if not self._auth.refresh_token_valid():
raise Exception('Refresh token has expired')

response = self._request_token(TOKEN_ENDPOINT, body={
'grant_type': 'refresh_token',
'refresh_token': self._auth.refresh_token(),
'access_token_ttl': ACCESS_TOKEN_TTL,
'refresh_token_ttl': REFRESH_TOKEN_TTL
})

self._auth.set_data(response.json_dict())

# TODO Add event trigger

return response
try:
if not self._auth.refresh_token_valid():
raise Exception('Refresh token has expired')
response = self._request_token(TOKEN_ENDPOINT, body={
'grant_type': 'refresh_token',
'refresh_token': self._auth.refresh_token(),
'access_token_ttl': ACCESS_TOKEN_TTL,
'refresh_token_ttl': REFRESH_TOKEN_TTL
})
self._auth.set_data(response.json_dict())
self.trigger(Events.refreshSuccess, response)
return response
except Exception as e:
self.trigger(Events.refreshError, e)
raise e

def logout(self):
response = self._request_token(REVOKE_ENDPOINT, body={
'token': self._auth.access_token()
})
self._auth.reset()
# TODO Add event trigger
return response
try:
response = self._request_token(REVOKE_ENDPOINT, body={
'token': self._auth.access_token()
})
self._auth.reset()
self.trigger(Events.logoutSuccess, response)
return response
except Exception as e:
self.trigger(Events.logoutError, e)
raise e

def inflate_request(self, request, skip_auth_check=False):
if not skip_auth_check:
Expand Down
1 change: 1 addition & 0 deletions ringcentral/subscription/events.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python
# encoding: utf-8


class Events:
connectionError = 'connectionError'
notification = 'notification'
Expand Down
63 changes: 33 additions & 30 deletions ringcentral/subscription/subscription.py
Expand Up @@ -148,34 +148,37 @@ def _subscribe_at_pubnub(self):
if not self.alive():
raise Exception('Subscription is not alive')

from pubnub import Pubnub

s_key = self._subscription['deliveryMode']['subscriberKey']
self._pubnub = Pubnub(subscribe_key=s_key, ssl_on=False, publish_key='')

def callback(message, channel=''):
self._notify(message)

def error(message):
self.trigger(Events.connectionError, message)

def connect(message):
pass

def reconnect(message):
pass

def disconnect(message):
pass

self._pubnub.subscribe(
self._subscription['deliveryMode']['address'],
callback=callback,
error=error,
connect=connect,
reconnect=reconnect,
disconnect=disconnect
)
from pubnub.pubnub import PubNub
from pubnub.pnconfiguration import PNConfiguration
from pubnub.callbacks import SubscribeCallback
from pubnub.enums import PNStatusCategory

pnconf = PNConfiguration()
pnconf.subscribe_key = self._subscription['deliveryMode']['subscriberKey']
self._pubnub = PubNub(pnconf)

subscription = self

class SubscribeCallbackImpl(SubscribeCallback):
def presence(self, pubnub, presence):
pass # handle incoming presence data

def status(self, pubnub, status):
if status.category == PNStatusCategory.PNUnexpectedDisconnectCategory:
subscription.trigger(Events.connectionError, 'Connectivity loas')
pass
elif status.category == PNStatusCategory.PNConnectedCategory:
pass
elif status.category == PNStatusCategory.PNReconnectedCategory:
pass
elif status.category == PNStatusCategory.PNDecryptionErrorCategory:
pass

def message(self, pubnub, pnmessage): # instance of PNMessageResult
subscription._notify(pnmessage.message)

self._pubnub.add_listener(SubscribeCallbackImpl())
self._pubnub.subscribe().channels(self._subscription['deliveryMode']['address']).execute()

def _notify(self, message):
message = self._decrypt(message)
Expand All @@ -185,7 +188,7 @@ def _decrypt(self, message):
if not self.alive():
raise Exception('Subscription is not alive')

from pubnub import AES
from Crypto.Cipher import AES

delivery_mode = self._subscription['deliveryMode']
is_encrypted = ('encryption' in delivery_mode) and ('encryptionKey' in delivery_mode)
Expand All @@ -201,7 +204,7 @@ def _decrypt(self, message):

def _unsubscribe_at_pubnub(self):
if self._pubnub and self.alive():
self._pubnub.unsubscribe(self._subscription['deliveryMode']['address'])
self._pubnub.unsubscribe().channels(self._subscription['deliveryMode']['address']).execute()

def _get_full_events_filter(self):
return [self._platform.create_url(e) for e in self._event_filters]
Expand Down
8 changes: 8 additions & 0 deletions ringcentral/test/testcase.py
Expand Up @@ -31,6 +31,14 @@ def get_sdk(self, mock):
text=''
)

matcher = re.compile('ps\.pndsn\.com')

mock.register_uri(
method=requests_mock.ANY,
url=matcher,
text=''
)

return sdk

def add(self, mock, method, url, body, status=200):
Expand Down
5 changes: 3 additions & 2 deletions setup.py
@@ -1,6 +1,6 @@
from distutils.core import setup

VERSION = '0.7.4'
VERSION = '0.7.5'

setup(
name='ringcentral',
Expand All @@ -20,7 +20,8 @@
keywords=['sdk', 'ringcentral', 'connect', 'platform', 'api', 'python'],
install_requires=[
'observable>=0.3.1',
'pubnub==3.*',
'pubnub==4.*',
'pycryptodome>=3.4.4',
'requests>=2.7.0'
],
classifiers=[]
Expand Down

0 comments on commit e5c8b34

Please sign in to comment.