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