]> git.ipfire.org Git - people/shoehn/ipfire.org.git/blob - webapp/ui_modules.py
talk: Update for Kamailio
[people/shoehn/ipfire.org.git] / webapp / ui_modules.py
1 #!/usr/bin/python
2
3 from __future__ import division
4
5 import hashlib
6 import logging
7 import operator
8 import re
9 import socket
10 import textile
11 import tornado.escape
12 import tornado.locale
13 import tornado.web
14 import unicodedata
15
16 import backend
17
18 class UIModule(tornado.web.UIModule):
19 @property
20 def accounts(self):
21 return self.handler.accounts
22
23 @property
24 def advertisements(self):
25 return self.handler.advertisements
26
27 @property
28 def banners(self):
29 return self.handler.banners
30
31 @property
32 def memcached(self):
33 return self.handler.memcached
34
35 @property
36 def releases(self):
37 return self.handler.releases
38
39 @property
40 def geoip(self):
41 return self.handler.geoip
42
43 @property
44 def news(self):
45 return self.handler.news
46
47 @property
48 def planet(self):
49 return self.handler.planet
50
51 @property
52 def talk(self):
53 return self.handler.talk
54
55 @property
56 def wishlist(self):
57 return self.handler.wishlist
58
59
60 class AdvertisementModule(UIModule):
61 def render(self, where):
62 assert where in ("download-splash",), where
63
64 ad = self.advertisements.get(where)
65 if not ad:
66 return ""
67
68 # Mark that advert has been shown.
69 ad.update_impressions()
70
71 return self.render_string("modules/ads/%s.html" % where, ad=ad)
72
73
74 class FireinfoDeviceTableModule(UIModule):
75 def render(self, devices):
76 return self.render_string("fireinfo/modules/table-devices.html",
77 devices=devices)
78
79
80 class FireinfoDeviceAndGroupsTableModule(UIModule):
81 def render(self, devices):
82 _ = self.locale.translate
83
84 groups = {}
85
86 for device in devices:
87 if not groups.has_key(device.cls):
88 groups[device.cls] = []
89
90 groups[device.cls].append(device)
91
92 # Sort all devices
93 for key in groups.keys():
94 groups[key].sort()
95
96 # Order the groups by their name
97 groups = groups.items()
98 groups.sort()
99
100 return self.render_string("fireinfo/modules/table-devices-and-groups.html",
101 groups=groups)
102
103
104 class FireinfoGeoTableModule(UIModule):
105 def render(self, items):
106 countries = []
107 other_countries = []
108 for code, value in items:
109 # Skip the satellite providers in this ranking
110 if code in (None, "A1", "A2"):
111 continue
112
113 name = self.geoip.get_country_name(code)
114
115 # Don't add countries with a small share on the list
116 if value < 0.01:
117 other_countries.append(name)
118 continue
119
120 country = backend.database.Row({
121 "code" : code,
122 "name" : name,
123 "value" : value,
124 })
125 countries.append(country)
126
127 return self.render_string("fireinfo/modules/table-geo.html",
128 countries=countries, other_countries=other_countries)
129
130
131 class LanguageNameModule(UIModule):
132 def render(self, language):
133 _ = self.locale.translate
134
135 if language == "de":
136 return _("German")
137 elif language == "en":
138 return _("English")
139 elif language == "es":
140 return _("Spanish")
141 elif language == "fr":
142 return _("French")
143 elif language == "it":
144 return _("Italian")
145 elif language == "nl":
146 return _("Dutch")
147 elif language == "pl":
148 return _("Polish")
149 elif language == "pt":
150 return _("Portuguese")
151 elif language == "ru":
152 return _("Russian")
153 elif language == "tr":
154 return _("Turkish")
155
156 return language
157
158
159 class MapModule(UIModule):
160 def render(self, latitude, longitude):
161 return self.render_string("modules/map.html", latitude=latitude, longitude=longitude)
162
163
164 class MenuModule(UIModule):
165 def render(self):
166 return self.render_string("modules/menu.html")
167
168
169 class MirrorItemModule(UIModule):
170 def render(self, item):
171 return self.render_string("modules/mirror-item.html", item=item)
172
173
174 class MirrorsTableModule(UIModule):
175 def render(self, mirrors, preferred_mirrors=[]):
176 return self.render_string("modules/mirrors-table.html",
177 mirrors=mirrors, preferred_mirrors=preferred_mirrors)
178
179
180 class NetBootMenuConfigModule(UIModule):
181 def render(self, release):
182 return self.render_string("netboot/menu-config.cfg", release=release)
183
184
185 class NetBootMenuHeaderModule(UIModule):
186 def render(self, title, releases):
187 id = unicodedata.normalize("NFKD", unicode(title)).encode("ascii", "ignore")
188 id = re.sub(r"[^\w]+", " ", id)
189 id = "-".join(id.lower().strip().split())
190
191 return self.render_string("netboot/menu-header.cfg", id=id,
192 title=title, releases=releases)
193
194
195 class NetBootMenuSeparatorModule(UIModule):
196 def render(self):
197 return self.render_string("netboot/menu-separator.cfg")
198
199
200 class NewsItemModule(UIModule):
201 def get_author(self, author):
202 # Get name of author
203 author = self.accounts.find(author)
204 if author:
205 return author.name
206 else:
207 _ = self.locale.translate
208 return _("Unknown author")
209
210 def render(self, item, uncut=True, announcement=False, show_heading=True):
211 # Get author
212 item.author = self.get_author(item.author_id)
213
214 if not uncut and len(item.text) >= 400:
215 item.text = item.text[:400] + "..."
216
217 # Render text
218 item.text = textile.textile(item.text.decode("utf8"))
219
220 return self.render_string("modules/news-item.html", item=item,
221 uncut=uncut, announcement=announcement, show_heading=show_heading)
222
223
224 class NewsLineModule(UIModule):
225 def render(self, item):
226 return self.render_string("modules/news-line.html", item=item)
227
228
229 class NewsTableModule(UIModule):
230 def render(self, news):
231 return self.render_string("modules/news-table.html", news=news)
232
233
234 class NewsYearNavigationModule(UIModule):
235 def render(self, active=None):
236 try:
237 active = int(active)
238 except:
239 active = None
240
241 return self.render_string("modules/news-year-nav.html",
242 active=active, years=self.news.years)
243
244
245 class PlanetSearchBoxModule(UIModule):
246 def render(self, query=None):
247 years = self.planet.get_years()
248
249 return self.render_string("modules/planet/search-box.html",
250 query=query, years=years)
251
252
253 class SidebarItemModule(UIModule):
254 def render(self):
255 return self.render_string("modules/sidebar-item.html")
256
257
258 class SidebarReleaseModule(UIModule):
259 def render(self):
260 return self.render_string("modules/sidebar-release.html",
261 latest=self.releases.get_latest())
262
263
264 class ReleaseItemModule(UIModule):
265 def render(self, release, latest=False):
266 arches = ("i586", "arm")
267
268 downloads = []
269 for arch in ("i586", "arm"):
270 files = []
271
272 for file in release.files:
273 if not file.arch == arch:
274 continue
275
276 files.append(file)
277
278 if files:
279 downloads.append((arch, files))
280
281 return self.render_string("modules/release-item.html",
282 release=release, latest=latest, downloads=downloads)
283
284
285 class SidebarBannerModule(UIModule):
286 def render(self, item=None):
287 if not item:
288 item = self.banners.get_random()
289
290 return self.render_string("modules/sidebar-banner.html", item=item)
291
292
293 class DownloadButtonModule(UIModule):
294 def render(self, release, text="Download now!"):
295 best_image = None
296
297 for file in release.files:
298 if file.type == "iso":
299 best_image = file
300 break
301
302 # Show nothing when there was no image found.
303 if not best_image:
304 return ""
305
306 return self.render_string("modules/download-button.html",
307 release=release, image=best_image)
308
309
310 class PlanetAuthorBoxModule(UIModule):
311 def render(self, author):
312 return self.render_string("planet/modules/author-box.html", author=author)
313
314
315 class PlanetEntryModule(UIModule):
316 def render(self, entry, show_avatar=True):
317 return self.render_string("modules/planet-entry.html",
318 entry=entry, show_avatar=show_avatar)
319
320
321 class ProgressBarModule(UIModule):
322 def render(self, value, colour=None):
323 value *= 100
324
325 return self.render_string("modules/progress-bar.html",
326 colour=colour, value=value)
327
328
329 class TalkCallLogModule(UIModule):
330 def render(self, account=None, viewer=None):
331 if (account is None or not self.current_user == account) \
332 and not self.current_user.is_admin():
333 raise RuntimeException("Insufficient permissions")
334
335 if viewer is None:
336 viewer = self.current_user
337
338 calls = self.talk.get_call_log(account)
339
340 return self.render_string("talk/modules/call-log.html",
341 calls=calls, viewer=viewer)
342
343
344 class TalkLinesModule(UIModule):
345 def render(self, account=None, show_account=False):
346 if (account is None or not self.current_user == account) \
347 and not self.current_user.is_admin():
348 raise RuntimeException("Insufficient permissions")
349
350 lines = self.talk.get_lines(account)
351
352 return self.render_string("talk/modules/lines.html",
353 show_account=show_account, lines=lines)
354
355
356 class TalkOngoingCallsModule(UIModule):
357 def render(self, account=None):
358 if (account is None or not self.current_user == account) \
359 and not self.current_user.is_admin():
360 raise RuntimeException("Insufficient permissions")
361
362 calls = self.talk.get_ongoing_calls(account)
363
364 if calls:
365 return self.render_string("talk/modules/ongoing-calls.html",
366 calls=calls)
367
368 return ""
369
370
371 class TrackerPeerListModule(UIModule):
372 def render(self, peers):
373 # Guess country code and hostname of the host
374 for peer in peers:
375 country_code = self.geoip.get_country(peer["ip"])
376 if country_code:
377 peer["country_code"] = country_code.lower()
378 else:
379 peer["country_code"] = "unknown"
380
381 try:
382 peer["hostname"] = socket.gethostbyaddr(peer["ip"])[0]
383 except:
384 peer["hostname"] = ""
385
386 return self.render_string("modules/tracker-peerlist.html",
387 peers=[backend.database.Row(p) for p in peers])
388
389
390 class WishlistModule(UIModule):
391 def render(self, wishes, short=False):
392 return self.render_string("wishlist/modules/wishlist.html",
393 wishes=wishes, short=short)
394
395
396 class WishModule(UIModule):
397 def render(self, wish, short=False):
398 progress_bar = "progress-bar-warning"
399
400 if wish.percentage >= 100:
401 progress_bar = "progress-bar-success"
402
403 return self.render_string("wishlist/modules/wish.html",
404 wish=wish, short=short, progress_bar=progress_bar)
405
406
407 class WishlistItemsModule(UIModule):
408 def render(self, wishlist_items):
409 return self.render_string("modules/wishlist-items.html",
410 wishlist_items=wishlist_items)
411
412
413 class DonationBoxModule(UIModule):
414 def render(self, reason_for_transfer=None):
415 if reason_for_transfer:
416 reason_for_transfer = "IPFire.org - %s" % reason_for_transfer
417
418 return self.render_string("modules/donation-box.html",
419 reason_for_transfer=reason_for_transfer)
420
421
422 class DonationButtonModule(UIModule):
423 # https://developer.paypal.com/docs/classic/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables/
424 COUNTRIES = (
425 "AU",
426 "AT",
427 "BE",
428 "BR",
429 "CA",
430 "CH",
431 "CN",
432 "DE",
433 "ES",
434 "GB",
435 "FR",
436 "IT",
437 "NL",
438 "PL",
439 "PT",
440 "RU",
441 "US",
442 )
443
444 LOCALES = (
445 "da_DK",
446 "he_IL",
447 "id_ID",
448 "ja_JP",
449 "no_NO",
450 "pt_BR",
451 "ru_RU",
452 "sv_SE",
453 "th_TH",
454 "zh_CN",
455 "zh_HK",
456 "zh_TW",
457 )
458
459 def render(self, reason_for_transfer=None, currency="EUR"):
460 if not reason_for_transfer:
461 reason_for_transfer = "IPFire.org"
462
463 primary = (currency == "EUR")
464
465 return self.render_string("modules/donation-button.html", primary=primary,
466 reason_for_transfer=reason_for_transfer, currency=currency, lc=self.lc)
467
468 @property
469 def lc(self):
470 """
471 Returns the locale of the user
472 """
473 try:
474 locale, delimiter, encoding = self.locale.code.partition(".")
475
476 # Break for languages in specific countries
477 if locale in self.LOCALES:
478 return locale
479
480 lang, delimiter, country_code = locale.partition("_")
481 print locale, "TEST", country_code
482
483 if country_code and country_code in self.COUNTRIES:
484 return country_code
485
486 lang = lang.upper()
487 if lang in self.COUNTRIES:
488 return lang
489 except:
490 pass
491
492 # If anything goes wrong, fall back to GB
493 return "GB"