From 30aeccdbfa1ffa179a5681dbcf58c08dec762d36 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Fri, 19 Oct 2018 09:39:26 +0100 Subject: [PATCH] people: List ongoing conferences Signed-off-by: Michael Tremer --- Makefile.am | 1 + src/backend/talk.py | 107 ++++++++++++--------- src/templates/people/base.html | 6 ++ src/templates/people/conferences.html | 57 +++++++++++ src/templates/people/modules/channels.html | 7 +- src/web/__init__.py | 1 + src/web/people.py | 6 ++ 7 files changed, 136 insertions(+), 49 deletions(-) create mode 100644 src/templates/people/conferences.html diff --git a/Makefile.am b/Makefile.am index 1424e824..43033d44 100644 --- a/Makefile.am +++ b/Makefile.am @@ -152,6 +152,7 @@ templates_newsletter_DATA = \ templates_newsletterdir = $(templatesdir)/newsletter templates_people_DATA = \ + src/templates/people/conferences.html \ src/templates/people/base.html \ src/templates/people/call.html \ src/templates/people/calls.html \ diff --git a/src/backend/talk.py b/src/backend/talk.py index 4f692f04..8eb2f37c 100644 --- a/src/backend/talk.py +++ b/src/backend/talk.py @@ -34,22 +34,24 @@ class Freeswitch(Object): for row in res: yield SIPRegistration(self, data=row) - def get_sip_channels(self, account): - res = self.db.query("SELECT * FROM channels \ - WHERE (direction = %s AND cid_num = %s) OR \ - (direction = %s AND (callee_num = %s OR callee_num = ANY(%s))) \ - ORDER BY created_epoch", - "inbound", account.sip_id, "outbound", account.sip_id, - account._all_telephone_numbers) + def _get_channels(self, query, *args): + res = self.db.query(query, *args) channels = [] - for row in res: c = Channel(self, data=row) channels.append(c) return channels + def get_sip_channels(self, account): + return self._get_channels("SELECT * FROM channels \ + WHERE (direction = %s AND cid_num = %s) OR \ + (direction = %s AND (callee_num = %s OR callee_num = ANY(%s))) \ + ORDER BY created_epoch", + "inbound", account.sip_id, "outbound", account.sip_id, + account._all_telephone_numbers) + def get_cdr_by_account(self, account, date=None, limit=None): res = self.db.query("SELECT * FROM cdr \ WHERE ((caller_id_number = ANY(%s) AND bleg_uuid IS NOT NULL) \ @@ -68,6 +70,18 @@ class Freeswitch(Object): if res: return CDR(self, data=res) + def get_conferences(self): + res = self.db.query("SELECT DISTINCT application_data AS handle FROM channels \ + WHERE application = %s AND application_data LIKE %s \ + ORDER BY application_data", "conference", "%%@ipfire.org") + + conferences = [] + for row in res: + c = Conference(self, row.handle) + conferences.append(c) + + return conferences + class SIPRegistration(object): def __init__(self, freeswitch, data): @@ -155,6 +169,11 @@ class Channel(object): def application_data(self): return self.data.application_data + @lazy_property + def conference(self): + if self.application == "conference": + return Conference(self.freeswitch, self.application_data) + @property def duration(self): return time.time() - self.data.created_epoch @@ -261,57 +280,51 @@ class CDR(object): return self.data.rtp_audio_in_mos -class Talk(Object): - def init(self): - # Connect to FreeSWITCH - self.freeswitch = Freeswitch(self.backend) - - # Conferences - - @property - def conferences(self): - conferences = [] - - for no in range(1, 10): - conference = Conference(self.backend, no) - conferences.append(conference) - - return conferences +class Conference(object): + def __init__(self, freeswitch, handle): + self.freeswitch = freeswitch + self.handle = handle - def get_conference(self, id): - for c in self.conferences: - if not c.sip_id == id: - continue + def __repr__(self): + return "<%s %s>" % (self.__class__.__name__, self.handle) - return c + def __len__(self): + return len(self.channels) + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.handle == other.handle -class Conference(Object): - def __init__(self, backend, no): - Object.__init__(self, backend) - self.no = no + def __iter__(self): + return iter(self.channels) - def __cmp__(self, other): - return cmp(self.no, other.no) + @lazy_property + def number(self): + m = re.match(r"conf(\d+)@", self.handle) + if m: + i = m.group(1) - @property - def name(self): - return "IPFire Conference Room %s" % self.no + return int(i) @property def sip_id(self): - return "%s" % (9000 + self.no) + return 900 + self.number - @property - def sip_url(self): - return "%s@ipfire.org" % self.sip_id + @lazy_property + def channels(self): + return self.freeswitch._get_channels("SELECT * FROM channels \ + WHERE application = %s AND application_data = %s \ + ORDER BY created_epoch", "conference", self.handle) - @property - def participants(self): - if not hasattr(self, "_participants"): - self._participants = self.backend.talk.get_ongoing_calls(sip_id=self.sip_id) - return self._participants +class Talk(Object): + def init(self): + # Connect to FreeSWITCH + self.freeswitch = Freeswitch(self.backend) + + @property + def conferences(self): + return self.freeswitch.get_conferences() def format_codec(name, bit_rate, bandwidth): diff --git a/src/templates/people/base.html b/src/templates/people/base.html index 44b3e913..342974a1 100644 --- a/src/templates/people/base.html +++ b/src/templates/people/base.html @@ -28,6 +28,12 @@ {{ _("Users") }} + +
diff --git a/src/templates/people/conferences.html b/src/templates/people/conferences.html new file mode 100644 index 00000000..8b0ac71e --- /dev/null +++ b/src/templates/people/conferences.html @@ -0,0 +1,57 @@ +{% extends "base.html" %} + +{% block title %}{{ _("Conferences") }}{% end block %} + +{% block content %} +
+
+

{{ _("Conferences") }}

+ + {% if conferences %} + {% for c in conferences %} +
+
+
{{ _("Conference Room %s") % c.number }}
+ +

+ {{ _("This conference room has one participant", "This conference room has %(num)s participants", len(c)) % { "num" : len(c) } }} +

+
+ +
    + {% for chan in c.channels %} +
  • +
    +
    + {% if chan.caller %} + {{ chan.caller }} + {% else %} + {{ chan.caller_name }} + {% end %} + + ({{ format_phone_number(chan.caller_number) }}) +
    + + {{ format_time(chan.duration) }} +
    + + + {% if chan.is_secure() %} + + {% end %} + + {{ chan.codec }} + +
  • + {% end %} +
+
+ {% end %} + {% else %} +

+ {{ _("There are currently no conferences") }} +

+ {% end %} +
+
+{% end block %} diff --git a/src/templates/people/modules/channels.html b/src/templates/people/modules/channels.html index 89f1d0d6..aa0959c5 100644 --- a/src/templates/people/modules/channels.html +++ b/src/templates/people/modules/channels.html @@ -11,9 +11,12 @@ {% if chan.direction == "inbound" %} - {% if chan.application == "conference" %} - CONFERENCE + {% if chan.conference %} + {{ _("Conference Room %s") % chan.conference.number }} + + ({{ _("One Participant", "%(num)s Participants", len(chan.conference)) % { "num" : len(chan.conference) } }}) + {% elif chan.application == "echo" %} {{ _("Echo Test") }} diff --git a/src/web/__init__.py b/src/web/__init__.py index 7072108c..20c3f2ce 100644 --- a/src/web/__init__.py +++ b/src/web/__init__.py @@ -255,6 +255,7 @@ class Application(tornado.web.Application): # people.ipfire.org self.add_handlers(r"people(\.dev)?\.ipfire\.org", [ (r"/", people.IndexHandler), + (r"/conferences", people.ConferencesHandler), (r"/search", people.SearchHandler), (r"/users", people.UsersHandler), (r"/users/(\w+)", people.UserHandler), diff --git a/src/web/people.py b/src/web/people.py index f6e615e4..7fbbe34d 100644 --- a/src/web/people.py +++ b/src/web/people.py @@ -88,6 +88,12 @@ class CallHandler(base.BaseHandler): self.render("people/call.html", account=account, call=call) +class ConferencesHandler(base.BaseHandler): + @tornado.web.authenticated + def get(self): + self.render("people/conferences.html", conferences=self.backend.talk.conferences) + + class SearchHandler(base.BaseHandler): @tornado.web.authenticated def get(self): -- 2.47.3