File: //home/arjun/projects/buyercall_new/buyercall/buyercall/blueprints/sms/tw_sms_tasks.py
import traceback
import logging as log
from datetime import datetime
from flask import current_app, url_for
from buyercall.app import create_celery_app
from buyercall.lib.util_twilio import subaccount_client
from buyercall.blueprints.sms.models import Message
from buyercall.blueprints.contacts.models import Contact
from buyercall.blueprints.phonenumbers.models import Phone
from buyercall.blueprints.partnership.models import PartnershipAccount, Partnership
from buyercall.blueprints.phonenumbers.routing import (
get_sms_routing_agents, get_agent_number
)
from buyercall.lib.util_webhooks import WebhookUtil
from buyercall.extensions import db
from buyercall.blueprints.filters import format_phone_number
celery = create_celery_app(current_app)
webhooker = WebhookUtil()
@celery.task
def tw_forward_sms(inbound_id, text, lead, message_info, **kwargs):
""" This function is used to send Twilio sms messages using celery. More information on bandwidth messaging
can be found here; https://www.twilio.com/docs/sms/tutorials/how-to-send-sms-messages-python
"""
# Query the inbound phone number and routing details
inbound = Phone.query.filter(Phone.id == inbound_id).first()
phonenumber = inbound.phonenumber
log.info('The Twilio inbound number phone number for smsing is {}'.format(phonenumber))
# import partnership information to get partnership id
partner_account = PartnershipAccount.query \
.filter(PartnershipAccount.id == inbound.partnership_account_id).first()
partner = Partnership.query.filter(Partnership.id == partner_account.partnership_id).first()
# Connect to Twilio client
twilio_client = subaccount_client(inbound.partnership_account.subscription.twilio_subaccount_sid, partner.id)
routing = inbound.routing_config['defaultRouting']
log.info('The Twilio inbound number routing config is {}'.format(routing))
agents = get_sms_routing_agents(routing)
lead_phone = format_phone_number(lead)
contact = Contact.query.filter(Contact.phonenumber_1 == lead_phone)\
.filter(Contact.partnership_account_id == inbound.partnership_account_id).first()
if contact:
if contact.firstname:
contact_name = "{} {} {}".format(contact.firstname, contact.lastname, lead_phone)
elif contact.caller_id:
contact_name = "{} {}".format(contact.caller_id, lead_phone)
else:
contact_name = lead_phone
partner_account = PartnershipAccount.query.filter(
PartnershipAccount.id == inbound.partnership_account_id
).first()
partner = Partnership.query.filter(Partnership.id == partner_account.partnership_id).first()
if partner.partner_url:
lead_contact_url = '{}/contacts/contact/{}'.format(partner.partner_url, contact.id)
else:
lead_contact_url = url_for('contacts.contact_lead_page', id=contact.id, _external=True)
else:
contact_name = 'unknown'
lead_contact_url = 'unavailable'
log.info('The url for the contact is {}'.format(lead_contact_url))
try:
agent_list = []
for agent in agents:
agent_phone_number = get_agent_number(agent, routing)
sms_agent_number = str(agent_phone_number[0])
log.info('The available agent contact number is {}'.format(sms_agent_number))
mod_body = 'FROM:{} MSG:{} REPLY: {}'.format(contact_name, text, lead_contact_url)
twilio_client.messages.create(
from_=phonenumber,
to=sms_agent_number,
body=mod_body
)
agent_list.append(agent.id)
log.info('A Twilio sms message has been successfully sent to agent phone number: {} using phone number {}'
.format(sms_agent_number, phonenumber))
except Exception:
log.info(traceback.format_exc())
log.info('The Twilio sms message could not be sent, either due to no agent to receive it o'
'r there was another error')
return
add_tw_message_lead(inbound_id, message_info, inbound.partnership_account_id, inbound.provider, None, agent_list)
@celery.task
def tw_send_sms(inbound_id, to, text, agent_list, **kwargs):
""" This function is used to send Twilio sms messages using celery. More information on twilio messaging
can be found here; https://www.twilio.com/docs/sms/tutorials/how-to-send-sms-messages-python
"""
# Query the inbound phone number and routing details
inbound = Phone.query.filter(Phone.id == inbound_id).first()
phonenumber = inbound.phonenumber
# import partnership information to get partnership id
partner_account = PartnershipAccount.query \
.filter(PartnershipAccount.id == inbound.partnership_account_id).first()
partner = Partnership.query.filter(Partnership.id == partner_account.partnership_id).first()
# Connect to Twilio client
twilio_client = subaccount_client(inbound.partnership_account.subscription.twilio_subaccount_sid, partner.id)
try:
message = twilio_client.messages.create(
from_=phonenumber,
to=to,
body=text)
log.info('A Twilio sms message has been successfully sent using phone number: {}'
.format(phonenumber))
log.info('The message sid is {}'.format(message.sid))
add_tw_message_lead(inbound_id, message, inbound.partnership_account_id, inbound.provider, '', agent_list)
except Exception:
log.info(traceback.format_exc())
log.info('The Twilio sms message could not be sent! That was an error')
@celery.task
def tw_forward_mms(inbound_id, text, lead, media, message_info, **kwargs):
""" This function is used to send Twilio sms messages using celery. More information on bandwidth messaging
can be found here; https://www.twilio.com/docs/sms/tutorials/how-to-send-sms-messages-python
"""
# Query the inbound phone number and routing details
inbound = Phone.query.filter(Phone.id == inbound_id).first()
phonenumber = inbound.phonenumber
# import partnership information to get partnership id
partner_account = PartnershipAccount.query \
.filter(PartnershipAccount.id == inbound.partnership_account_id).first()
partner = Partnership.query.filter(Partnership.id == partner_account.partnership_id).first()
# Connect to the Twilio client
twilio_client = subaccount_client(inbound.partnership_account.subscription.twilio_subaccount_sid, partner.id)
lead_phone = format_phone_number(lead)
contact = Contact.query.filter(Contact.phonenumber_1 == lead_phone) \
.filter(Contact.partnership_account_id == inbound.partnership_account_id).first()
if contact:
if contact.firstname:
contact_name = '{} {} - {}'.format(contact.firstname, contact.lastname, lead_phone)
elif contact.caller_id:
contact_name = "{} - {}".format(contact.caller_id, lead_phone)
else:
contact_name = lead_phone
partner_account = PartnershipAccount.query \
.filter(PartnershipAccount.id == inbound.partnership_account_id).first()
partner = Partnership.query.filter(Partnership.id == partner_account.partnership_id).first()
if partner.partner_url:
lead_contact_url = partner.partner_url + '/contacts/contact/' + str(contact.id)
else:
lead_contact_url = url_for('contacts.contact_lead_page', id=contact.id, _external=True)
else:
contact_name = 'unknown'
lead_contact_url = 'unavailable'
log.info('The url for the contact is {}'.format(lead_contact_url))
log.info('The Twilio inbound number phone number for mmsing is {}'.format(phonenumber))
routing = inbound.routing_config['defaultRouting']
log.info('The Twilio inbound number routing config is {}'.format(routing))
agents = get_sms_routing_agents(routing)
try:
agent_list = []
for agent in agents:
agent_phone_number = get_agent_number(agent, routing)
sms_agent_number = str(agent_phone_number[0])
mod_body = 'FROM:' + contact_name + ' MSG:' + text + ' REPLY:' + lead_contact_url
log.info('The available agent contact number is {}'.format(sms_agent_number))
twilio_client.messages.create(
from_=phonenumber,
to=sms_agent_number,
body=mod_body,
media_url=media,
)
agent_list.append(agent.id)
log.info('A Twilio mms message has been successfully sent to agent phone number: {} using phone number {}'
.format(sms_agent_number, phonenumber))
except Exception:
log.info(traceback.format_exc())
log.info('The Twilio mms message could not be sent, '
'either due to no agent to receive it or there was another error')
return
add_tw_message_lead(inbound_id, message_info, inbound.partnership_account_id, inbound.provider, media, agent_list)
@celery.task
def tw_send_mms(inbound_id, to, text, media, agent_list, **kwargs):
""" This function is used to send Twilio mms messages using celery. More information on Twilio messaging
can be found here; https://www.twilio.com/docs/sms/tutorials/how-to-send-sms-messages-python
"""
# Query the inbound phone number and routing details
inbound = Phone.query.filter(Phone.id == inbound_id).first()
phonenumber = inbound.phonenumber
log.info('The Twilio inbound number phone number for mmsing is {}'.format(phonenumber))
log.info('the media is {}'.format(media))
# import partnership information to get partnership id
partner_account = PartnershipAccount.query \
.filter(PartnershipAccount.id == inbound.partnership_account_id).first()
partner = Partnership.query.filter(Partnership.id == partner_account.partnership_id).first()
# Connect to the Twilio client
twilio_client = subaccount_client(inbound.partnership_account.subscription.twilio_subaccount_sid, partner.id)
try:
message = twilio_client.messages.create(
from_=phonenumber,
to=to,
body=text,
media_url=media,
)
log.info('A Twilio mms message has been successfully sent using phone number: {}'
.format(phonenumber))
log.info('The message sid is {}'.format(message.sid))
add_tw_message_lead(inbound_id, message, inbound.partnership_account_id, inbound.provider, media, agent_list)
except Exception as e:
log.info(traceback.format_exc())
log.info('The Twilio mms message could not be sent, either due to no agent to receive it or '
'there was another error')
@celery.task
def add_tw_message_lead(inbound_id, message_info, partnership_account_id, provider, media, agent_list, **kwargs):
"""
Add sms lead message to the messages table
"""
msg_status = ''
if message_info.direction == 'outbound-api':
direct = 'outbound'
msg_status = 'sent'
else:
direct = message_info.direction
# The sender's formatted phone number
if direct == 'inbound':
msg_status = 'received'
format_phone = format_phone_number(message_info.from_)
else:
format_phone = format_phone_number(message_info.to)
contact = Contact.query.filter(Contact.phonenumber_1 == format_phone).filter(
Contact.partnership_account_id == partnership_account_id
).first()
if not contact:
contact_entry = Contact(
phonenumber_1=format_phone,
partnership_account_id=partnership_account_id
)
db.session.add(contact_entry)
db.session.commit()
# from buyercall.blueprints.mobile.utils import send_agent_push_notification
# send_agent_push_notification(contact_entry)
log.info('The message contact has been added')
new_contact = Contact.query.filter(Contact.phonenumber_1 == format_phone).filter(
Contact.partnership_account_id == partnership_account_id
).first()
date = str(message_info.date_created)
media_url = media
formatted_pn = format_phone_number(message_info.from_)
log.info('The media_url is: {}'.format(media_url))
try:
if new_contact:
new_contact_id = new_contact.id
new_contact.updated_on = date
if media_url:
eventype = 'mms'
url = media_url
else:
eventype = 'sms'
url = ''
if not agent_list:
agent_list = []
message = Message(
type=eventype,
provider=provider,
provider_message_id=message_info.sid,
provider_message_date=message_info.date_created,
to=message_info.to,
from_=formatted_pn,
body_text=message_info.body,
media_url=url,
status=msg_status,
direction=direct,
inbound_id=inbound_id,
partnership_account_id=partnership_account_id,
contact_id=new_contact_id,
originating_number=formatted_pn,
agent_id=agent_list
)
db.session.add(message)
db.session.commit()
if direct == 'outbound':
webhooker.trigger_generic_webhook('operational_send_message', message.id)
elif direct == 'inbound':
webhooker.trigger_generic_webhook('operational_receive_message', message.id)
else:
log.error('There no new contact')
except Exception as e:
log.error('Error: Unable to add message lead')
@celery.task
def sms_rule_call_lead(inbound_id, lead_number, agent_id, **kwargs):
from buyercall.blueprints.leads.models import Lead
from buyercall.blueprints.phonenumbers.models import Phone
from buyercall.blueprints.agents.models import Agent
from buyercall.blueprints.phonenumbers.tasks import connect_lead_to_agent
inbound = Phone.query.filter(Phone.id == inbound_id).first()
all_inbound_lead = Lead.query.filter(
Lead.partnership_account_id == Lead.inbound_id == inbound_id
).all()
if all_inbound_lead:
for row in all_inbound_lead:
lead_no = format_phone_number(row.phonenumber)
log.info('The phonenumber is {}'.format(row.phonenumber))
if lead_no == lead_number:
progress_status = row.progress_status
else:
progress_status = 'new lead'
agent = Agent.query.filter(Agent.id == agent_id).first()
log.info('Is the agent available now? {}'.format(agent.available_now))
# Return contact details
contact_lead = Contact.query.filter(Contact.phonenumber_1 == lead_number).filter(
Contact.partnership_account_id == inbound.partnership_account_id
).first()
if not contact_lead:
return 'Contact lead with phone nummber: {} not found'.format(lead_number), 400
try:
lead = Lead(
partnership_account_id=inbound.partnership_account_id,
firstname=contact_lead.firstname,
lastname=contact_lead.lastname,
phonenumber=contact_lead.phonenumber_1,
email=contact_lead.email,
starttime=datetime.utcnow(),
call_type='outbound',
my_phone=inbound.phonenumber,
inbound_id=inbound_id,
agent_id=agent_id,
progress_status=progress_status,
status='ringing',
contact_id=contact_lead.id,
)
lead.save()
# A hack to specify how to contact the agent
contact_using = 'phone'
call_settings = {
'agents': [{'id': agent_id, 'contactUsing': contact_using}]
}
connect_lead_to_agent.delay(lead.id, agent_id, call_settings)
except Exception as e:
log.error('An outbound call to agent and lead can not be made based on the '
'sms rule for the inbound id: {}'.format(inbound_id))
log.error(traceback.format_exc())
return ''