Commit 869e514b authored by okhin's avatar okhin 🚴

Fixing some small bugs

parent a5151972
Pipeline #110 passed with stage
in 2 seconds
...@@ -89,7 +89,7 @@ class Channel(object): ...@@ -89,7 +89,7 @@ class Channel(object):
''' '''
def __init__(self, config, name): def __init__(self, config, name):
self.config = config self.config = config
self.channel = name self.name = name
def status(self): def status(self):
''' '''
......
...@@ -75,7 +75,7 @@ class PiphoneJSONEncoder(json.JSONEncoder): ...@@ -75,7 +75,7 @@ class PiphoneJSONEncoder(json.JSONEncoder):
return { 'caller': obj.caller return { 'caller': obj.caller
, 'callee': obj.callee , 'callee': obj.callee
, 'callid': obj.id , 'callid': obj.id
, 'url': obj.url() , 'url': obj.url
, 'history': obj.history , 'history': obj.history
, 'owner': obj.owner } , 'owner': obj.owner }
else: else:
...@@ -114,6 +114,7 @@ def authenticated(f): ...@@ -114,6 +114,7 @@ def authenticated(f):
bottle_logger.exception(e) bottle_logger.exception(e)
abort(403, e) abort(403, e)
except Exception as e: except Exception as e:
bottle_logger.exception(e)
abort(500, e) abort(500, e)
return f(db, *args, **kwargs) return f(db, *args, **kwargs)
return wrapped return wrapped
...@@ -166,7 +167,7 @@ def hold_bridge(): ...@@ -166,7 +167,7 @@ def hold_bridge():
raise e raise e
@asyncio.coroutine @asyncio.coroutine
def listen(): def listen(db):
''' '''
Start listening on the websocket Start listening on the websocket
''' '''
...@@ -181,7 +182,7 @@ def listen(): ...@@ -181,7 +182,7 @@ def listen():
try: try:
event = yield from ws.recv() event = yield from ws.recv()
# Let's call the applications function # Let's call the applications function
yield from dispatch(json.loads(event)) yield from dispatch(json.loads(event), db)
except websockets.exceptions.ConnectionClosed as e: except websockets.exceptions.ConnectionClosed as e:
ws_logger.warning("Connexion closed") ws_logger.warning("Connexion closed")
ws_logger.exception(e) ws_logger.exception(e)
...@@ -194,7 +195,7 @@ def listen(): ...@@ -194,7 +195,7 @@ def listen():
ws.close() ws.close()
@asyncio.coroutine @asyncio.coroutine
def dispatch(self, event): def dispatch(event, db):
""" """
Let's work on our events. Parse them and do request on the ARI API. Event is Let's work on our events. Parse them and do request on the ARI API. Event is
a dict loaded from JSON. a dict loaded from JSON.
...@@ -204,7 +205,7 @@ def dispatch(self, event): ...@@ -204,7 +205,7 @@ def dispatch(self, event):
if 'channel' not in event: if 'channel' not in event:
return return
call_id = re.sub('-\d+$', '', event['channel']['id']) call_id = re.sub('-\d+$', '', event['channel']['id'])
call = Call.load(call_id, self.db) call = Call.load(call_id, db)
call.event_handler(event) call.event_handler(event)
class Call(object): class Call(object):
...@@ -224,31 +225,32 @@ class Call(object): ...@@ -224,31 +225,32 @@ class Call(object):
self.owner = owner self.owner = owner
if callid == None: if callid == None:
self.id = str(uuid.uuid4()) self.id = str(uuid.uuid4())
self.db = db
self.event_handler({'type': 'Created', 'timestamp': datetime.datetime.now().isoformat(), 'channel': {'id': 'Init'}})
else: else:
self.id = callid self.id = callid
self.db = db
self.event_handler({'type': 'Created', 'timestamp': datetime.datetime.now().isoformat(), 'channel': {'id': 'Init'}})
except Exception as e: except Exception as e:
phone_logger.exception(e) phone_logger.exception(e)
raise e raise e
@property
def url(self): def url(self):
return ''.join(['/calls/', self.id]) return ''.join(['/calls/', self.id])
@property
def state(self): def state(self):
sort = sorted(self.history, reverse=True, key=itemgetter(1)) sort = sorted(self.history, reverse=True, key=itemgetter(1))
return sort[0][0] return sort[0][0]
@classmethod @classmethod
def load(cls, callid, db): def load(cls, callid, db):
phone_logger.debug("Loading call {}".format(callid,)) phone_logger.debug("Loading call {} from db {}".format(callid, db,))
try: try:
results = db.execute('SELECT caller, callee, owner, callid, history FROM calls WHERE callid = ?;', (callid,)) results = db.execute('SELECT caller, callee, owner, callid, history FROM calls WHERE callid = ?;', (callid,))
result = results.fetchone() result = results.fetchone()
assert len(result) == 5 assert len(result) == 5
object = cls(result[0], result[1], result[2], result[3]) object = cls(result[0], result[1], result[2], result[3], db=db)
object.history = json.loads(result[4]) object.history = json.loads(result[4])
object.db = db
return object return object
except Exception as e: except Exception as e:
phone_logger.exception(e) phone_logger.exception(e)
...@@ -267,6 +269,13 @@ class Call(object): ...@@ -267,6 +269,13 @@ class Call(object):
There's a new event related to our call There's a new event related to our call
''' '''
state = event['type'] state = event['type']
try:
if self.state.startswith(state):
# We're alreaydy in this state, we just need to noop
return
except IndexError:
if state in self.actions:
getattr(self, self.actions[state])(event=event)
if state in self.actions: if state in self.actions:
getattr(self, self.actions[state])(event=event) getattr(self, self.actions[state])(event=event)
...@@ -298,7 +307,7 @@ class Call(object): ...@@ -298,7 +307,7 @@ class Call(object):
We received a DTMF sequence We received a DTMF sequence
''' '''
try: try:
assert self.state().startswith('Up') assert self.state.startswith('Up')
# The only thing we want to do is to call the callee if we press 1 # The only thing we want to do is to call the callee if we press 1
if event['digit'] != '1': if event['digit'] != '1':
return return
...@@ -318,12 +327,13 @@ class Call(object): ...@@ -318,12 +327,13 @@ class Call(object):
channel = ari.Channel(config['asterisk'], self.id + '-' + sanitize_phonenumber(self.callee)) channel = ari.Channel(config['asterisk'], self.id + '-' + sanitize_phonenumber(self.callee))
channel.originate(endpoint) channel.originate(endpoint)
except AssertionError as e: except AssertionError as e:
phone_logger.error("Received a DTMF sequence out le being in a '{}' state, ignoring: {}".format(self.state(), event['digit'])) phone_logger.error("Received a DTMF sequence out le being in a '{}' state, ignoring: {}".format(self.state, event['digit']))
def change(self, event): def change(self, event):
''' '''
Let's change the state of the call Let's change the state of the call
''' '''
# First we need to check if it's really a change ie, if the new state is not the previous one
self.update((':'.join([event['channel']['state'], event['channel']['id'].split('-')[-1]]), event['timestamp'],)) self.update((':'.join([event['channel']['state'], event['channel']['id'].split('-')[-1]]), event['timestamp'],))
phone_logger.info("New state for call {}: {}".format(event['channel']['id'], event['channel']['state'])) phone_logger.info("New state for call {}: {}".format(event['channel']['id'], event['channel']['state']))
# We now need to take action according to our new state # We now need to take action according to our new state
...@@ -371,7 +381,7 @@ class Call(object): ...@@ -371,7 +381,7 @@ class Call(object):
try: try:
endpoint = 'SIP/' + sanitize_phonenumber(self.caller) + '@' + config['asterisk']['sip-context'] endpoint = 'SIP/' + sanitize_phonenumber(self.caller) + '@' + config['asterisk']['sip-context']
channel = ari.Channel(config['asterisk'], self.id + '-' + sanitize_phonenumber(self.caller)) channel = ari.Channel(config['asterisk'], self.id + '-' + sanitize_phonenumber(self.caller))
channel.originate() channel.originate(endpoint)
except Exception as e: except Exception as e:
phone_logger.exception(e) phone_logger.exception(e)
raise e raise e
...@@ -387,14 +397,15 @@ class Call(object): ...@@ -387,14 +397,15 @@ class Call(object):
, (self.caller, self.callee, self.owner, self.id, json.dumps(self.history))) , (self.caller, self.callee, self.owner, self.id, json.dumps(self.history)))
self.db.commit() self.db.commit()
except Exception as e: except Exception as e:
bottle_logger.exception(e)
phone_logger.exception(e) phone_logger.exception(e)
raise e raise e
def start(): def start(db):
global running global running
running = True running = True
threads.submit(app.run, server='paste') threads.submit(app.run, server='paste')
loop.run_until_complete(listen()) loop.run_until_complete(listen(db))
def stop(): def stop():
global running global running
...@@ -435,7 +446,7 @@ def calls(db, callid=None): ...@@ -435,7 +446,7 @@ def calls(db, callid=None):
bottle_logger.debug("Found {} results: {}".format(len(rows), rows)) bottle_logger.debug("Found {} results: {}".format(len(rows), rows))
assert len(rows) == 1 assert len(rows) == 1
call = Call.load(callid, db) call = Call.load(callid, db)
head = {'call': call.url(), 'user': request.params['api'], 'hits': 1} head = {'call': call.url, 'user': request.params['api'], 'hits': 1}
return {'head': head, 'data': call} return {'head': head, 'data': call}
except AssertionError as e: except AssertionError as e:
bottle_logger.debug("Not exactly one results found, this is an issue") bottle_logger.debug("Not exactly one results found, this is an issue")
...@@ -454,11 +465,12 @@ def originate(db, callid=None): ...@@ -454,11 +465,12 @@ def originate(db, callid=None):
bottle_logger.debug("POST {}".format(request.fullpath)) bottle_logger.debug("POST {}".format(request.fullpath))
try: try:
if callid is not None: if callid is not None:
call = Call(request.params['caller'], request.params['callee'], request.params['api'], callid=request.params['callid'], db=db) call = Call(request.params['caller'], request.params['callee'], request.params['api'], callid=callid, db=db)
else: else:
call = Call(request.params['caller'], request.params['callee'], request.params['api'], db=db) call = Call(request.params['caller'], request.params['callee'], request.params['api'], db=db)
bottle_logger.debug("Originate a call: {}".format(json.dumps(call, cls=PiphoneJSONEncoder))) bottle_logger.debug("Originate a call: {}".format(json.dumps(call, cls=PiphoneJSONEncoder)))
head = {'call': call.url() call.save()
head = {'call': call.url
, 'user': request.params['api'] , 'user': request.params['api']
, 'hits': 1} , 'hits': 1}
return {'header': head, 'data': call} return {'header': head, 'data': call}
...@@ -471,6 +483,6 @@ if __name__ == '__main__': ...@@ -471,6 +483,6 @@ if __name__ == '__main__':
db = sqlite3.connect(config['piphone']['db']) db = sqlite3.connect(config['piphone']['db'])
phone_logger.info("Starting the piphone SIP backend") phone_logger.info("Starting the piphone SIP backend")
try: try:
start() start(db)
except (KeyboardInterrupt, SystemExit): except (KeyboardInterrupt, SystemExit):
stop() stop()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment