templates_talk_modules_DATA = \
src/templates/talk/modules/accounts-list.html \
+ src/templates/talk/modules/cdr.html \
src/templates/talk/modules/channels.html \
src/templates/talk/modules/registrations.html
return self._search_one("(|(&(objectClass=sipUser)(sipAuthenticationUser=%s)) \
(&(objectClass=sipRoutingObject)(sipLocalAddress=%s)))" % (sip_id, sip_id))
+ def get_by_phone_number(self, number):
+ return self._search_one("(&(objectClass=posixAccount) \
+ (|(sipAuthenticationUser=%s)(telephoneNumber=%s)(homePhone=%s)(mobile=%s)))" \
+ % (number, number, number, number))
+
# Session stuff
def _cleanup_expired_sessions(self):
return sip_registrations
+ def get_cdr(self, limit=None):
+ return self.backend.talk.freeswitch.get_cdr_by_account(self, limit=limit)
+
@property
def telephone_numbers(self):
return self._telephone_numbers + self.mobile_telephone_numbers \
return channels
+ def get_cdr_by_account(self, account, limit=None):
+ res = self.db.query("SELECT * FROM cdr \
+ WHERE caller_id_number = %s OR destination_number = %s \
+ ORDER BY end_stamp DESC LIMIT %s", account.sip_id, account.sip_id, limit)
+
+ for row in res:
+ yield CDR(self, data=row)
+
class SIPRegistration(object):
def __init__(self, freeswitch, data):
return "%s: %s" % (key_negotiation.upper(), cipher_suite.replace("_", "-"))
+class CDR(object):
+ def __init__(self, freeswitch, data):
+ self.freeswitch = freeswitch
+ self.data = data
+
+ @property
+ def backend(self):
+ return self.freeswitch.backend
+
+ @property
+ def direction(self):
+ if self.data.bleg_uuid:
+ return "inbound"
+
+ return "outbound"
+
+ @lazy_property
+ def caller(self):
+ return self.backend.accounts.get_by_phone_number(self.data.caller_id_number)
+
+ @property
+ def caller_number(self):
+ return self.data.caller_id_number
+
+ @lazy_property
+ def callee(self):
+ return self.backend.accounts.get_by_phone_number(self.data.destination_number)
+
+ @property
+ def callee_number(self):
+ return self.data.destination_number
+
+ @property
+ def time_start(self):
+ return self.data.start_stamp
+
+ @property
+ def time_answered(self):
+ return self.data.answer_stamp
+
+ @property
+ def duration(self):
+ return self.data.duration
+
+ @property
+ def codec(self):
+ return self.data.write_codec
+
+ @property
+ def user_agent(self):
+ return self.data.user_agent
+
+
class Talk(Object):
def init(self):
# Connect to FreeSWITCH
{% block main %}
{% module TalkChannels(current_user) %}
+
+ <div class="card">
+ <div class="card-body">
+ <h4>{{ _("Your Recent Calls") }}</h4>
+
+ {% module TalkCDR(current_user, limit=5) %}
+ </div>
+ </div>
{% end block %}
--- /dev/null
+<table class="table table-sm mb-0">
+ <thead>
+ <tr>
+ <th></th>
+ <th class="text-right">{{ _("Duration") }}</th>
+ </tr>
+ </thead>
+
+ <tbody>
+ {% for c in cdr %}
+ <tr>
+ <td>
+ {% if c.direction == "inbound" %}
+ <span class="oi oi-arrow-right text-danger"></span>
+
+ {% if c.callee %}
+ <a href="/users/{{ c.callee.uid }}">{{ c.callee }}</a>
+ {% else %}
+ {{ c.callee_number }}
+ {% end %}
+ {% elif c.direction == "outbound" %}
+ <span class="oi oi-arrow-left text-success"></span>
+
+ {% if c.caller %}
+ <a href="/users/{{ c.caller.uid }}">{{ c.caller }}</a>
+ {% else %}
+ {{ c.caller_number }}
+ {% end %}
+ {% end %}
+
+ <br>
+
+ <span class="small text-muted">
+ {{ " - ".join((e for e in (c.codec, c.user_agent) if e)) }}
+ </span>
+ </td>
+
+ <td class="text-right">
+ {{ locale.format_date(c.time_start, relative=False) }} <br>
+
+ {% if c.time_answered %}
+ <span class="text-muted">{{ format_time(c.duration) }}</span>
+ {% else %}
+ <span class="text-danger">{{ _("Not Answered") }}</span>
+ {% end %}
+ </td>
+ </tr>
+ {% end %}
+ </tbody>
+</table>
# Talk
"TalkAccountsList" : talk.AccountsListModule,
+ "TalkCDR" : talk.CDRModule,
"TalkChannels" : talk.ChannelsModule,
"TalkRegistrations" : talk.RegistrationsModule,
return self.render_string("talk/modules/accounts-list.html", accounts=accounts)
+class CDRModule(ui_modules.UIModule):
+ def render(self, account, limit=None):
+ cdr = account.get_cdr(limit=limit)
+
+ return self.render_string("talk/modules/cdr.html", account=account, cdr=cdr)
+
+
class ChannelsModule(ui_modules.UIModule):
def render(self, account):
channels = self.backend.talk.freeswitch.get_sip_channels(account)