Skip to content

Commit

Permalink
[WIP] Call flow being implemented, it gather information and connect …
Browse files Browse the repository at this point in the history
…clients
  • Loading branch information
danimaribeiro committed Dec 1, 2018
1 parent 0d316df commit 7ed6b83
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 6 deletions.
22 changes: 18 additions & 4 deletions voice_twilio/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,42 @@ class TwilioController(http.Controller):
# return str(response)

def new_incoming_call(self, voice_call_id, vals):
resp = VoiceResponse()
resp.say("Você será atendido agora", voice="alice", language="pt-BR")
flow_obj = request.env['twilio.voice.flow'].sudo()
flow = flow_obj.next_flow(voice_call_id.voice_flow_sequence)
resp = flow.generate_twiml()
voice_call_id.voice_flow_sequence += 1
return str(resp)

def call_completed(self, voice_call_id, vals):
voice_call_id.action_call_completed(vals)
return 'true'

def call_in_progress(self, voice_call_id, vals):
flow_obj = request.env['twilio.voice.flow'].sudo()
flow = flow_obj.next_flow(voice_call_id.voice_flow_sequence)
if not flow:
resp = VoiceResponse()
resp.hangup()
return str(resp)
else:
voice_call_id.voice_flow_sequence += 1
return str(flow.generate_twiml())

@http.route('/twilio/voice', type='http', auth="public",
cors="*", csrf=False)
def twilio_voice_request(self, **vals):
print(vals)
voice_obj = request.env['twilio.voice.call'].sudo()
voice_call_id = voice_obj.register_new_call(vals)
call_status = vals['CallStatus']
if call_status == 'ringing':
return self.new_incoming_call(voice_call_id, vals)
elif call_status == 'completed':
return self.call_completed(voice_call_id, vals)
elif call_status == 'in-progress':
return self.call_in_progress(voice_call_id, vals)
else:
resp = VoiceResponse()
resp.say("Desculpe ",
voice="alice", language="pt-BR")
resp.hangup()
return str(resp)

Expand Down
17 changes: 17 additions & 0 deletions voice_twilio/models/COPYRIGHT
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

Most of the files are

Copyright (c) 2018-2018 Trustcode Sistemas Empresariais LTDA.

and published under the Odoo Enterprise Edition License,
as described in the LICENSE file.

Some files may also contain contributions from third
parties. In this case the original copyright of
the contributions can be traced through the
history of the source version control system.

When that is not the case, the files contain a prominent
notice stating the original copyright and applicable
license, or come with their own dedicated COPYRIGHT
and/or LICENSE file.
45 changes: 45 additions & 0 deletions voice_twilio/models/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

For copyright information, please see the COPYRIGHT file.

Odoo Enterprise Edition is published under the Odoo Enterprise
Edition License v1.0, as included below.

This license applies only to the part of this software that is
not distributed as part of Odoo Community Edition.

********************************************************************************

Odoo Enterprise Edition License v1.0
Copyright (C) 2015 Odoo S.A.

This software and associated files (the "Software") can only be used (executed,
modified, executed after modifications) with a valid Odoo Enterprise
Subscription for the correct number of users.

With a valid Partnership Agreement with Odoo S.A., the above permissions
are also granted, as long as the usage is limited to a testing or development
environment.

You may develop Odoo modules based on the Software and distribute them
under the license of your choice, provided that it is compatible with the terms
of the Odoo Enterprise Edition License (For example: LGPL, MIT, or proprietary
licenses similar to this one).

You may use Odoo modules published under any license along with the Software,
provided that their license is compatible with the terms of the Odoo Enterprise
License (Including, but not limited to, any module published on the Odoo Apps
Store on odoo.com)

It is forbidden to publish, distribute, sublicense, or sell copies of the Software
or modified copies of the Software.

The above copyright notice and this permission notice must be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
2 changes: 2 additions & 0 deletions voice_twilio/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@

from . import twilio_voice_call
from . import voice_flow
from . import res_partner
from . import mail_channel
8 changes: 8 additions & 0 deletions voice_twilio/models/mail_channel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# © 2018 Danimar Ribeiro <danimaribeiro@gmail.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo import fields, models


class MailChannel(models.Model):
_inherit = 'mail.channel'
10 changes: 10 additions & 0 deletions voice_twilio/models/res_partner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# © 2018 Danimar Ribeiro <danimaribeiro@gmail.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo import fields, models


class ResPartner(models.Model):
_inherit = 'res.partner'

twilio_client = fields.Char(string="Twilio Client Identifier")
3 changes: 2 additions & 1 deletion voice_twilio/models/twilio_voice_call.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
class TwilioVoiceCall(models.Model):
_name = 'twilio.voice.call'
_description = 'Voice Call from Twilio'
_order = 'calling_date desc'

name = fields.Char(string="Name", size=50, required=True)
sid = fields.Char(string="Unique Identifier", size=40, readonly=True)
Expand All @@ -28,7 +29,7 @@ class TwilioVoiceCall(models.Model):
('talking', 'Talking'),
('completed', 'Completed')])
call_duration = fields.Integer(string="Duration")
voice_flow_sequence = fields.Integer(default=0)
voice_flow_sequence = fields.Integer(default=-1)
last_gather_key = fields.Char()
last_gather_value = fields.Char()

Expand Down
74 changes: 73 additions & 1 deletion voice_twilio/models/voice_flow.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
# © 2018 Danimar Ribeiro <danimaribeiro@gmail.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)


import logging
from odoo import fields, models

_logger = logging.getLogger(__name__)

try:
from twilio.twiml.voice_response import Dial, Gather, VoiceResponse
except ImportError:
_logger.error('Cannot import twilio library', exc_info=True)


class TwilioVoiceFlow(models.Model):
_name = 'twilio.voice.flow'
Expand Down Expand Up @@ -41,3 +48,68 @@ class TwilioVoiceFlow(models.Model):

filter_key = fields.Char(string="Filter Key")
filter_value = fields.Char(string="Filter Value")

def next_flow(self, sequence):
flow = self.search(
[('sequence', '>', sequence)], limit=1, order='sequence asc')
return flow

def _get_dial_to(self):
if self.to_partner_id and self.to_partner_id.twilio_client:
return [self.to_partner_id.twilio_client]
elif self.to_mail_channel_id:
partners = self.to_mail_channel_id.channel_last_seen_partner_ids
return [x.twilio_client for x in partners if x.twilio_client]
return None

def _generate_say(self, response):
if self.say_message and len(self.say_message) > 0:
response.say(self.say_message, voice="alice", language="pt-BR")

def _generate_gather(self, response):
gather = Gather()
self._generate_say(gather)

if self.gather_possible_values:
values = [x.strip() for x in
self.gather_possible_values.split('\n')]
if ";" in values[0]:
gather.input = 'dtmf speech'
gather.speechTimeout = 'auto'
elif values[0].isdigit():
gather.input = 'dtmf'
else:
gather.input = 'speech'
gather.speechTimeout = 'auto'

response.append(gather)

def _generate_dial(self, response):
self._generate_say(response)
dial_to = self._get_dial_to()
if len(dial_to) > 0:
dial = Dial()
for item in dial_to[:10]:
dial.client(item)
response.append(dial)
else:
response.say('Nobody is available to answer your call!')

def generate_twiml(self):
response = VoiceResponse()
if self.flow_type == 'say':
self._generate_say(response)
elif self.flow_type == 'gather':
self._generate_gather(response)
elif self.flow_type == 'connect':
self._generate_dial(response)

base_url = self.env['ir.config_parameter'].sudo().get_param(
'twilio.base.url')
if not base_url:
base_url = self.env['ir.config_parameter'].sudo().get_param(
'web.base.url')
response.say('Nenhuma pessoa para atender', voice='alice', language='pt-BR')
response.redirect(base_url + '/twilio/voice')
print(str(response))
return response
15 changes: 15 additions & 0 deletions voice_twilio/views/twilio_voice_call.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@
</field>
</record>

<record id="view_twilio_voice_call_tree" model="ir.ui.view">
<field name="name">view_twilio_voice_call_tree</field>
<field name="model">twilio.voice.call</field>
<field name="arch" type="xml">
<tree>
<field name="calling_date" />
<field name="name" />
<field name="state"/>
<field name="from_number"/>
<field name="to_number"/>
<field name="type" />
</tree>
</field>
</record>

<record id="action_twilio_voice_call" model="ir.actions.act_window">
<field name="name">Voice Calls</field>
<field name="res_model">twilio.voice.call</field>
Expand Down

0 comments on commit 7ed6b83

Please sign in to comment.