]>
Commit | Line | Data |
---|---|---|
66862195 MT |
1 | #!/usr/bin/python |
2 | ||
77431b9c MT |
3 | import re |
4 | ||
66862195 MT |
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({ | |
77431b9c | 13 | "database" : "kamailio", |
66862195 MT |
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): | |
77431b9c | 36 | res = self.db.get("SELECT 1 FROM location WHERE username = %s \ |
66862195 MT |
37 | AND expires >= NOW() LIMIT 1", sip_id) |
38 | ||
39 | if res: | |
40 | return True | |
41 | ||
42 | return False | |
43 | ||
77431b9c MT |
44 | def get_lines(self, account=None): |
45 | accounts_cache = {} | |
66862195 | 46 | |
77431b9c | 47 | if account and not account.is_talk_enabled(): |
66862195 MT |
48 | return [] |
49 | ||
77431b9c MT |
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") | |
66862195 MT |
57 | |
58 | result = [] | |
59 | for row in res: | |
77431b9c MT |
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 | |
66862195 | 70 | |
77431b9c MT |
71 | # Check if TLS is used |
72 | row.tls_enabled = row.socket.startswith("tls:") | |
66862195 MT |
73 | |
74 | # Cut off everything after ; | |
75 | row.location, sep, rest = row.location.partition(";") | |
76 | ||
77 | result.append(row) | |
78 | ||
79 | return result | |
80 | ||
77431b9c MT |
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): | |
66862195 MT |
95 | accounts_cache = {} |
96 | ||
97 | result = [] | |
98 | for row in entries: | |
77431b9c MT |
99 | if replace_sip_uris: |
100 | row["caller"] = self._process_sip_uri(row.caller) | |
101 | ||
66862195 | 102 | try: |
77431b9c | 103 | row["caller_account"] = accounts_cache[row.caller] |
66862195 | 104 | except KeyError: |
77431b9c | 105 | row["caller_account"] = accounts_cache[row.caller] = \ |
66862195 MT |
106 | self.accounts.get_by_sip_id(row.caller) |
107 | ||
77431b9c MT |
108 | if replace_sip_uris: |
109 | row["called"] = self._process_sip_uri(row.called) | |
110 | ||
66862195 | 111 | try: |
77431b9c | 112 | row["called_account"] = accounts_cache[row.called] |
66862195 | 113 | except KeyError: |
77431b9c | 114 | row["called_account"] = accounts_cache[row.called] = \ |
66862195 MT |
115 | self.accounts.get_by_sip_id(row.called) |
116 | ||
117 | if not row.called_account: | |
77431b9c | 118 | row["called_conference"] = self.get_conference(row.called) |
66862195 | 119 | else: |
77431b9c MT |
120 | row["called_conference"] = None |
121 | ||
122 | try: | |
123 | row["time"] = datetime.datetime.fromutctimestamp(row.time) | |
124 | except: | |
125 | pass | |
66862195 MT |
126 | |
127 | result.append(row) | |
128 | ||
129 | return result | |
130 | ||
131 | def get_call_log(self, account, limit=25): | |
77431b9c MT |
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) | |
66862195 MT |
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 | ||
77431b9c MT |
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 | ||
66862195 | 149 | if sip_id: |
77431b9c MT |
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) | |
66862195 | 156 | else: |
77431b9c MT |
157 | res = self.db.query("SELECT from_uri AS caller, to_uri AS called, \ |
158 | start_time AS time FROM dialog ORDER BY time") | |
66862195 | 159 | |
77431b9c | 160 | return self._process_cdr(res, replace_sip_uris=True) |
66862195 MT |
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): | |
77431b9c MT |
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) | |
66862195 MT |
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(): | |
77431b9c MT |
230 | if not invitee.sip_id: |
231 | continue | |
232 | ||
66862195 MT |
233 | if invitee.sip_id in participants: |
234 | continue | |
235 | ||
236 | invitees.append(invitee) | |
237 | ||
238 | return invitees |