]> git.ipfire.org Git - ipfire.org.git/commitdiff
talk: Add CDR
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 11 Oct 2018 13:40:40 +0000 (14:40 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 11 Oct 2018 13:40:40 +0000 (14:40 +0100)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/backend/accounts.py
src/backend/talk.py
src/templates/talk/index.html
src/templates/talk/modules/cdr.html [new file with mode: 0644]
src/web/__init__.py
src/web/talk.py

index 9454dca354143d33015d599a25385ea2f426f2c7..afc86076d74cf83e636c02b0ff190a6c67bc70eb 100644 (file)
@@ -171,6 +171,7 @@ templates_talkdir = $(templatesdir)/talk
 
 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
 
index 4d2171235d2f1ac5a84ba99cc2d9045b1a242ba2..20a3b6dfa6284388ce291b90ee780ea032aefa3b 100644 (file)
@@ -98,6 +98,11 @@ class Accounts(Object):
                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):
@@ -308,6 +313,9 @@ class Account(Object):
 
                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 \
index 7fec3afb425aba1f0431c936b7bbaae8f4408714..cc923dbfc4c6f8009d8ba03b116bbdc2d7097710 100644 (file)
@@ -48,6 +48,14 @@ class Freeswitch(Object):
 
                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):
@@ -169,6 +177,59 @@ class Channel(object):
                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
index 268f9c7a4933b0822b522fce8f06690b9c377a47..f692ae6e5b792144b0f2d2c2b13baf48bf39b024 100644 (file)
@@ -4,4 +4,12 @@
 
 {% 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 %}
diff --git a/src/templates/talk/modules/cdr.html b/src/templates/talk/modules/cdr.html
new file mode 100644 (file)
index 0000000..ce7b854
--- /dev/null
@@ -0,0 +1,50 @@
+<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>
index 97a50dec41a19717099b5f5c88d4a1e879f96827..f897e8220fcf1d7e7a92c4485fc3e2dfc1b6e943 100644 (file)
@@ -57,6 +57,7 @@ class Application(tornado.web.Application):
 
                                # Talk
                                "TalkAccountsList"     : talk.AccountsListModule,
+                               "TalkCDR"              : talk.CDRModule,
                                "TalkChannels"         : talk.ChannelsModule,
                                "TalkRegistrations"    : talk.RegistrationsModule,
 
index fb9f3d87fbd8a2fe2c9a3eb4a4e7af9936e3272d..8ce8e6c468c6632cb7f2bf39dd7bcf652d9543cc 100644 (file)
@@ -71,6 +71,13 @@ class AccountsListModule(ui_modules.UIModule):
                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)