]> git.ipfire.org Git - ipfire.org.git/blame - src/backend/talk.py
Drop gravatar
[ipfire.org.git] / src / backend / talk.py
CommitLineData
66862195
MT
1#!/usr/bin/python
2
77431b9c
MT
3import re
4
5ac74b02 5from . import database
66862195 6
11347e46 7from .misc import Object
13e89ccc
MT
8from .decorators import *
9
10class Freeswitch(Object):
11 @lazy_property
12 def db(self):
13 credentials = {
14 "host" : self.settings.get("freeswitch_database_host"),
15 "database" : self.settings.get("freeswitch_database_name", "freeswitch"),
16 "user" : self.settings.get("freeswitch_database_user"),
17 "password" : self.settings.get("freeswitch_database_password"),
18 }
19
20 return database.Connection(**credentials)
21
66862195
MT
22
23class Talk(Object):
13e89ccc
MT
24 def init(self):
25 # Connect to FreeSWITCH
26 self.freeswitch = Freeswitch(self.backend)
27
66862195
MT
28 def get_phonebook(self, account=None):
29 accounts = []
30 for a in self.accounts.list():
31 if account and a == account:
32 continue
33
34 if not a.is_talk_enabled():
35 continue
36
37 accounts.append(a)
38
39 return accounts
40
41 def user_is_online(self, sip_id):
77431b9c 42 res = self.db.get("SELECT 1 FROM location WHERE username = %s \
66862195
MT
43 AND expires >= NOW() LIMIT 1", sip_id)
44
45 if res:
46 return True
47
48 return False
49
77431b9c
MT
50 def get_lines(self, account=None):
51 accounts_cache = {}
66862195 52
77431b9c 53 if account and not account.is_talk_enabled():
66862195
MT
54 return []
55
77431b9c
MT
56 if account:
57 res = self.db.query("SELECT contact AS location, expires, user_agent, socket \
58 FROM location WHERE domain = %s AND username = %s ORDER BY expires DESC",
59 "ipfire.org", account.sip_id)
60 else:
61 res = self.db.query("SELECT username, domain, contact AS location, \
62 expires, user_agent, socket FROM location ORDER BY username, expires DESC")
66862195
MT
63
64 result = []
65 for row in res:
77431b9c
MT
66 if account:
67 row.account = account
68 elif row.username:
69 try:
70 row.account = accounts_cache[row.username]
71 except KeyError:
72 row.account = accounts_cache[row.username] = \
73 self.accounts.get_by_sip_id(row.username)
74 else:
75 row.account = None
66862195 76
77431b9c
MT
77 # Check if TLS is used
78 row.tls_enabled = row.socket.startswith("tls:")
66862195
MT
79
80 # Cut off everything after ;
81 row.location, sep, rest = row.location.partition(";")
82
83 result.append(row)
84
85 return result
86
77431b9c
MT
87 def _process_sip_uri(self, sip_uri):
88 sip_uri, delimiter, rest = sip_uri.partition(";")
89
90 m = re.match(r"^sip:([0-9]{4})@ipfire\.org", sip_uri)
91 if m:
92 return m.group(1)
93
94 # Remove trailing default port
95 if sip_uri.endswith(":5060"):
96 sip_uri = sip_uri.replace(":5060", "")
97
98 return sip_uri
99
100 def _process_cdr(self, entries, replace_sip_uris=False):
66862195
MT
101 accounts_cache = {}
102
103 result = []
104 for row in entries:
77431b9c
MT
105 if replace_sip_uris:
106 row["caller"] = self._process_sip_uri(row.caller)
107
66862195 108 try:
77431b9c 109 row["caller_account"] = accounts_cache[row.caller]
66862195 110 except KeyError:
77431b9c 111 row["caller_account"] = accounts_cache[row.caller] = \
66862195
MT
112 self.accounts.get_by_sip_id(row.caller)
113
77431b9c
MT
114 if replace_sip_uris:
115 row["called"] = self._process_sip_uri(row.called)
116
66862195 117 try:
77431b9c 118 row["called_account"] = accounts_cache[row.called]
66862195 119 except KeyError:
77431b9c 120 row["called_account"] = accounts_cache[row.called] = \
66862195
MT
121 self.accounts.get_by_sip_id(row.called)
122
123 if not row.called_account:
77431b9c 124 row["called_conference"] = self.get_conference(row.called)
66862195 125 else:
77431b9c
MT
126 row["called_conference"] = None
127
128 try:
129 row["time"] = datetime.datetime.fromutctimestamp(row.time)
130 except:
131 pass
66862195
MT
132
133 result.append(row)
134
135 return result
136
137 def get_call_log(self, account, limit=25):
77431b9c
MT
138 if account:
139 res = self.db.query("SELECT * FROM cdr WHERE (caller = %s OR called = %s) \
140 ORDER BY time DESC LIMIT %s", account.sip_id, account.sip_id, limit)
141 else:
142 res = self.db.query("SELECT * FROM cdr ORDER BY time DESC LIMIT %s", limit)
66862195
MT
143
144 return self._process_cdr(res)
145
a69e87a1
MT
146 def get_channels(self, account=None):
147 channels = []
148 for c in a.list_channels():
149 if account and not account.sip_id in (c.caller, c.callee):
150 continue
5ac74b02 151
a69e87a1 152 channels.append(c)
5ac74b02 153
a69e87a1 154 return sorted(channels)
5ac74b02 155
a69e87a1
MT
156 def get_channel(self, channel_id, account=None):
157 channels = self.get_channels(account=account)
40818cf2 158
a69e87a1
MT
159 for channel in channels:
160 if channel.id == channel_id:
161 return channel
40818cf2 162
66862195
MT
163 def get_ongoing_calls(self, account=None, sip_id=None):
164 if account and sip_id is None:
165 sip_id = account.sip_id
166
77431b9c
MT
167 # If the given account does not have a SIP ID,
168 # we not need to search for any active sessions
169 if sip_id is None:
170 return []
171
66862195 172 if sip_id:
77431b9c
MT
173 sip_id = "sip:%s@%%" % sip_id
174
175 res = self.db.query("SELECT from_uri AS caller, \
176 to_uri AS called, start_time AS time FROM dialog \
177 WHERE from_uri LIKE %s OR to_uri LIKE %s ORDER BY time",
178 sip_id, sip_id)
66862195 179 else:
77431b9c
MT
180 res = self.db.query("SELECT from_uri AS caller, to_uri AS called, \
181 start_time AS time FROM dialog ORDER BY time")
66862195 182
77431b9c 183 return self._process_cdr(res, replace_sip_uris=True)
66862195 184
66862195
MT
185 # Favourites
186
187 def get_favourite_contacts(self, account, limit=6):
77431b9c
MT
188 res = self.db.query("SELECT src_user AS caller, dst_ouser AS called, \
189 COUNT(*) AS count FROM acc WHERE method = %s AND src_user = %s AND \
190 dst_ouser BETWEEN %s AND %s AND time >= NOW() - INTERVAL '1 year' \
191 GROUP BY caller, called ORDER BY count DESC LIMIT %s",
192 "INVITE", account.sip_id, "1000", "1999", limit)
66862195
MT
193
194 return self._process_cdr(res)
195
196 # Conferences
197
198 @property
199 def conferences(self):
200 conferences = []
201
202 for no in range(1, 10):
203 conference = Conference(self.backend, no)
204 conferences.append(conference)
205
206 return conferences
207
208 def get_conference(self, id):
209 for c in self.conferences:
210 if not c.sip_id == id:
211 continue
212
213 return c
214
215
216class Conference(Object):
217 def __init__(self, backend, no):
218 Object.__init__(self, backend)
219 self.no = no
220
221 def __cmp__(self, other):
222 return cmp(self.no, other.no)
223
224 @property
225 def name(self):
226 return "IPFire Conference Room %s" % self.no
227
228 @property
229 def sip_id(self):
230 return "%s" % (9000 + self.no)
231
232 @property
233 def sip_url(self):
234 return "%s@ipfire.org" % self.sip_id
235
236 @property
237 def participants(self):
238 if not hasattr(self, "_participants"):
239 self._participants = self.backend.talk.get_ongoing_calls(sip_id=self.sip_id)
240
241 return self._participants