]> git.ipfire.org Git - people/shoehn/ipfire.org.git/blob - webapp/backend/talk.py
70a4172437f3d5bbbaec69a4442c06be55e67de0
[people/shoehn/ipfire.org.git] / webapp / backend / talk.py
1 #!/usr/bin/python
2
3 import database
4
5 from misc import Object
6
7 class Talk(Object):
8 def init(self):
9 db_args = self.backend.db._db_args
10 db_args.update({
11 "database" : "yate",
12 })
13
14 self._db = database.Connection(**db_args)
15
16 @property
17 def db(self):
18 return self._db
19
20 def get_phonebook(self, account=None):
21 accounts = []
22 for a in self.accounts.list():
23 if account and a == account:
24 continue
25
26 if not a.is_talk_enabled():
27 continue
28
29 accounts.append(a)
30
31 return accounts
32
33 def user_is_online(self, sip_id):
34 res = self.db.get("SELECT 1 FROM lines WHERE username = %s \
35 AND expires >= NOW() LIMIT 1", sip_id)
36
37 if res:
38 return True
39
40 return False
41
42 def get_trunks(self):
43 res = self.db.query("SELECT * FROM accounts WHERE enabled = TRUE \
44 ORDER BY description, account")
45
46 return res
47
48 def get_lines(self, account):
49 if not account.is_talk_enabled():
50 return []
51
52 res = self.db.query("SELECT location, expires, user_agent FROM lines \
53 WHERE username = %s ORDER BY expires DESC", account.sip_id)
54
55 result = []
56 for row in res:
57 # Check if TLS is used
58 row.tls_enabled = row.location.startswith("sip/sips:") or \
59 "transport=TLS" in row.location
60
61 # Strip a leading sip/
62 if row.location.startswith("sip/"):
63 row.location = row.location[4:]
64
65 # Cut off everything after ;
66 row.location, sep, rest = row.location.partition(";")
67
68 result.append(row)
69
70 return result
71
72 def _process_cdr(self, entries):
73 accounts_cache = {}
74
75 result = []
76 for row in entries:
77 try:
78 row.caller_account = accounts_cache[row.caller]
79 except KeyError:
80 row.caller_account = accounts_cache[row.caller] = \
81 self.accounts.get_by_sip_id(row.caller)
82
83 try:
84 row.called_account = accounts_cache[row.called]
85 except KeyError:
86 row.called_account = accounts_cache[row.called] = \
87 self.accounts.get_by_sip_id(row.called)
88
89 if not row.called_account:
90 row.called_conference = self.get_conference(row.called)
91 else:
92 row.called_conference = None
93
94 result.append(row)
95
96 return result
97
98 def get_call_log(self, account, limit=25):
99 res = self.db.query("SELECT * FROM cdr \
100 WHERE ((direction = 'incoming' AND called = %s) OR (direction = 'outgoing' AND caller = %s)) \
101 AND (status = 'answered' OR \
102 (status = 'ringing' AND (reason = 'hangup' OR reason = 'Request Terminated'))) \
103 AND NOT (status = 'outgoing' AND reason = 'pickup') \
104 AND ended = TRUE ORDER BY time DESC LIMIT %s", account.sip_id, account.sip_id, limit)
105
106 return self._process_cdr(res)
107
108 def get_ongoing_calls(self, account=None, sip_id=None):
109 if account and sip_id is None:
110 sip_id = account.sip_id
111
112 if sip_id:
113 res = self.db.query("SELECT * FROM cdr \
114 WHERE direction = 'incoming' AND (caller = %s OR called = %s) \
115 AND status = 'answered' AND NOT ended \
116 ORDER BY time", sip_id, sip_id)
117 else:
118 res = self.db.query("SELECT * FROM cdr \
119 WHERE direction = 'incoming' AND \
120 status = 'answered' AND NOT ended \
121 ORDER BY time")
122
123 return self._process_cdr(res)
124
125 def initiate_call(self, caller, called, when=None):
126 self.db.execute("INSERT INTO dialout(caller, called, not_before) \
127 VALUES(%s, %s, %s)", caller, called, when)
128
129 # Favourites
130
131 def get_favourite_contacts(self, account, limit=6):
132 ignored_numbers = ["9999", account.sip_id, ""]
133
134 res = self.db.query("SELECT called, %s AS caller, COUNT(*) AS count FROM cdr \
135 WHERE direction = 'outgoing' AND caller = %s AND status = 'answered' \
136 AND NOT called = ANY(%s) GROUP BY called ORDER BY count DESC LIMIT %s",
137 account.sip_id, account.sip_id, ignored_numbers, limit)
138
139 return self._process_cdr(res)
140
141 # Conferences
142
143 @property
144 def conferences(self):
145 conferences = []
146
147 for no in range(1, 10):
148 conference = Conference(self.backend, no)
149 conferences.append(conference)
150
151 return conferences
152
153 def get_conference(self, id):
154 for c in self.conferences:
155 if not c.sip_id == id:
156 continue
157
158 return c
159
160
161 class Conference(Object):
162 def __init__(self, backend, no):
163 Object.__init__(self, backend)
164 self.no = no
165
166 def __cmp__(self, other):
167 return cmp(self.no, other.no)
168
169 @property
170 def name(self):
171 return "IPFire Conference Room %s" % self.no
172
173 @property
174 def sip_id(self):
175 return "%s" % (9000 + self.no)
176
177 @property
178 def sip_url(self):
179 return "%s@ipfire.org" % self.sip_id
180
181 @property
182 def participants(self):
183 if not hasattr(self, "_participants"):
184 self._participants = self.backend.talk.get_ongoing_calls(sip_id=self.sip_id)
185
186 return self._participants
187
188 @property
189 def invitees(self):
190 invitees = []
191 participants = [p.caller for p in self.participants]
192
193 for invitee in self.backend.talk.get_phonebook():
194 if invitee.sip_id in participants:
195 continue
196
197 invitees.append(invitee)
198
199 return invitees