]> git.ipfire.org Git - people/shoehn/ipfire.org.git/blob - webapp/backend/talk.py
Huge update for fireinfo, introducting talk and nopaste
[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 = "transport=TLS" in row.location
59
60 # Strip a leading sip/
61 if row.location.startswith("sip/"):
62 row.location = row.location[4:]
63
64 # Cut off everything after ;
65 row.location, sep, rest = row.location.partition(";")
66
67 result.append(row)
68
69 return result
70
71 def _process_cdr(self, entries):
72 accounts_cache = {}
73
74 result = []
75 for row in entries:
76 try:
77 row.caller_account = accounts_cache[row.caller]
78 except KeyError:
79 row.caller_account = accounts_cache[row.caller] = \
80 self.accounts.get_by_sip_id(row.caller)
81
82 try:
83 row.called_account = accounts_cache[row.called]
84 except KeyError:
85 row.called_account = accounts_cache[row.called] = \
86 self.accounts.get_by_sip_id(row.called)
87
88 if not row.called_account:
89 row.called_conference = self.get_conference(row.called)
90 else:
91 row.called_conference = None
92
93 result.append(row)
94
95 return result
96
97 def get_call_log(self, account, limit=25):
98 res = self.db.query("SELECT * FROM cdr \
99 WHERE ((direction = 'incoming' AND called = %s) OR (direction = 'outgoing' AND caller = %s)) \
100 AND (status = 'answered' OR \
101 (status = 'ringing' AND (reason = 'hangup' OR reason = 'Request Terminated'))) \
102 AND NOT (status = 'outgoing' AND reason = 'pickup') \
103 AND ended = TRUE ORDER BY time DESC LIMIT %s", account.sip_id, account.sip_id, limit)
104
105 return self._process_cdr(res)
106
107 def get_ongoing_calls(self, account=None, sip_id=None):
108 if account and sip_id is None:
109 sip_id = account.sip_id
110
111 if sip_id:
112 res = self.db.query("SELECT * FROM cdr \
113 WHERE direction = 'incoming' AND (caller = %s OR called = %s) \
114 AND status = 'answered' AND NOT ended \
115 ORDER BY time", sip_id, sip_id)
116 else:
117 res = self.db.query("SELECT * FROM cdr \
118 WHERE direction = 'incoming' AND \
119 status = 'answered' AND NOT ended \
120 ORDER BY time")
121
122 return self._process_cdr(res)
123
124 def initiate_call(self, caller, called, when=None):
125 self.db.execute("INSERT INTO dialout(caller, called, not_before) \
126 VALUES(%s, %s, %s)", caller, called, when)
127
128 # Favourites
129
130 def get_favourite_contacts(self, account, limit=6):
131 ignored_numbers = ["9999", account.sip_id, ""]
132
133 res = self.db.query("SELECT called, %s AS caller, COUNT(*) AS count FROM cdr \
134 WHERE direction = 'outgoing' AND caller = %s AND status = 'answered' \
135 AND NOT called = ANY(%s) GROUP BY called ORDER BY count DESC LIMIT %s",
136 account.sip_id, account.sip_id, ignored_numbers, limit)
137
138 return self._process_cdr(res)
139
140 # Conferences
141
142 @property
143 def conferences(self):
144 conferences = []
145
146 for no in range(1, 10):
147 conference = Conference(self.backend, no)
148 conferences.append(conference)
149
150 return conferences
151
152 def get_conference(self, id):
153 for c in self.conferences:
154 if not c.sip_id == id:
155 continue
156
157 return c
158
159
160 class Conference(Object):
161 def __init__(self, backend, no):
162 Object.__init__(self, backend)
163 self.no = no
164
165 def __cmp__(self, other):
166 return cmp(self.no, other.no)
167
168 @property
169 def name(self):
170 return "IPFire Conference Room %s" % self.no
171
172 @property
173 def sip_id(self):
174 return "%s" % (9000 + self.no)
175
176 @property
177 def sip_url(self):
178 return "%s@ipfire.org" % self.sip_id
179
180 @property
181 def participants(self):
182 if not hasattr(self, "_participants"):
183 self._participants = self.backend.talk.get_ongoing_calls(sip_id=self.sip_id)
184
185 return self._participants
186
187 @property
188 def invitees(self):
189 invitees = []
190 participants = [p.caller for p in self.participants]
191
192 for invitee in self.backend.talk.get_phonebook():
193 if invitee.sip_id in participants:
194 continue
195
196 invitees.append(invitee)
197
198 return invitees