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