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) \
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):
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
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):
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}{{ _("Conferences") }}{% end block %}
+
+{% block content %}
+ <div class="row justify-content-center">
+ <div class="col col-md-8">
+ <h1>{{ _("Conferences") }}</h1>
+
+ {% if conferences %}
+ {% for c in conferences %}
+ <div class="card mb-3" name="{{ c.handle }}">
+ <div class="card-body">
+ <h5 class="card-title">{{ _("Conference Room %s") % c.number }}</h5>
+
+ <p class="card-text small text-muted">
+ {{ _("This conference room has one participant", "This conference room has %(num)s participants", len(c)) % { "num" : len(c) } }}
+ </p>
+ </div>
+
+ <ul class="list-group list-group-flush">
+ {% for chan in c.channels %}
+ <li class="list-group-item">
+ <div class="d-flex w-100 justify-content-between">
+ <div>
+ {% if chan.caller %}
+ <a href="/users/{{ chan.caller.uid }}">{{ chan.caller }}</a>
+ {% else %}
+ {{ chan.caller_name }}
+ {% end %}
+
+ <span class="text-muted">({{ format_phone_number(chan.caller_number) }})</span>
+ </div>
+
+ <span>{{ format_time(chan.duration) }}</span>
+ </div>
+
+ <span class="text-muted small">
+ {% if chan.is_secure() %}
+ <span class="fas fa-lock" title="{{ chan.secure }}"></span>
+ {% end %}
+
+ {{ chan.codec }}
+ </span>
+ </li>
+ {% end %}
+ </ul>
+ </div>
+ {% end %}
+ {% else %}
+ <p class="text-muted text-center my-5">
+ {{ _("There are currently no conferences") }}
+ </p>
+ {% end %}
+ </div>
+ </div>
+{% end block %}