]> git.openstreetmap.org Git - osqa.git/blob - forum/templatetags/extra_tags.py
Closes OSQA 320, True Gravatar Support.
[osqa.git] / forum / templatetags / extra_tags.py
1 import time
2 import os
3 import posixpath
4 import datetime
5 import math
6 import re
7 import logging
8 from django import template
9 from django.utils.encoding import smart_unicode
10 from django.utils.safestring import mark_safe
11 from forum.models import Question, Answer, QuestionRevision, AnswerRevision, NodeRevision
12 from django.utils.translation import ugettext as _
13 from django.utils.translation import ungettext
14 from django.utils import simplejson
15 from forum import settings
16 from django.template.defaulttags import url as default_url
17 from forum import skins
18 from forum.utils import html
19 from django.core.urlresolvers import reverse
20
21 register = template.Library()
22
23 GRAVATAR_TEMPLATE = ('<img class="gravatar" width="%(size)s" height="%(size)s" '
24 'src="http://www.gravatar.com/avatar/%(gravatar_hash)s'
25 '?s=%(size)s&amp;d=%(default)s&amp;r=%(rating)s" '
26 'alt="%(username)s\'s gravatar image" />')
27
28 @register.simple_tag
29 def gravatar(user, size):
30     try:
31         gravatar = user['gravatar']
32         username = user['username']
33     except (TypeError, AttributeError, KeyError):
34         gravatar = user.gravatar
35         username = user.username
36     return mark_safe(GRAVATAR_TEMPLATE % {
37     'size': size,
38     'gravatar_hash': gravatar,
39     'default': settings.GRAVATAR_DEFAULT_IMAGE,
40     'rating': settings.GRAVATAR_ALLOWED_RATING,
41     'username': template.defaultfilters.urlencode(username),
42     })
43
44
45 @register.simple_tag
46 def get_score_badge(user):
47     if user.is_suspended():
48         return _("(suspended)")
49
50     BADGE_TEMPLATE = '<span class="score" title="%(reputation)s %(reputationword)s">%(reputation)s</span>'
51     if user.gold > 0 :
52         BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '<span title="%(gold)s %(badgesword)s">'
53         '<span class="badge1">&#9679;</span>'
54         '<span class="badgecount">%(gold)s</span>'
55         '</span>')
56     if user.silver > 0:
57         BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '<span title="%(silver)s %(badgesword)s">'
58         '<span class="silver">&#9679;</span>'
59         '<span class="badgecount">%(silver)s</span>'
60         '</span>')
61     if user.bronze > 0:
62         BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '<span title="%(bronze)s %(badgesword)s">'
63         '<span class="bronze">&#9679;</span>'
64         '<span class="badgecount">%(bronze)s</span>'
65         '</span>')
66     BADGE_TEMPLATE = smart_unicode(BADGE_TEMPLATE, encoding='utf-8', strings_only=False, errors='strict')
67     return mark_safe(BADGE_TEMPLATE % {
68     'reputation' : user.reputation,
69     'gold' : user.gold,
70     'silver' : user.silver,
71     'bronze' : user.bronze,
72     'badgesword' : _('badges'),
73     'reputationword' : _('reputation points'),
74     })
75
76
77 @register.simple_tag
78 def get_age(birthday):
79     current_time = datetime.datetime(*time.localtime()[0:6])
80     year = birthday.year
81     month = birthday.month
82     day = birthday.day
83     diff = current_time - datetime.datetime(year, month, day, 0, 0, 0)
84     return diff.days / 365
85
86 @register.simple_tag
87 def diff_date(date, limen=2):
88     if not date:
89         return _('unknown')
90
91     now = datetime.datetime.now()
92     diff = now - date
93     days = diff.days
94     hours = int(diff.seconds/3600)
95     minutes = int(diff.seconds/60)
96
97     if days > 2:
98         if date.year == now.year:
99             return date.strftime("%b %d at %H:%M")
100         else:
101             return date.strftime("%b %d '%y at %H:%M")
102     elif days == 2:
103         return _('2 days ago')
104     elif days == 1:
105         return _('yesterday')
106     elif minutes >= 60:
107         return ungettext('%(hr)d hour ago', '%(hr)d hours ago', hours) % {'hr':hours}
108     elif diff.seconds >= 60:
109         return ungettext('%(min)d min ago', '%(min)d mins ago', minutes) % {'min':minutes}
110     else:
111         return ungettext('%(sec)d sec ago', '%(sec)d secs ago', diff.seconds) % {'sec':diff.seconds}
112
113 @register.simple_tag
114 def media(url):
115     url = skins.find_media_source(url)
116     if url:
117         url = '///' + settings.FORUM_SCRIPT_ALIAS + '/m/' + url
118         return posixpath.normpath(url)
119
120 class ItemSeparatorNode(template.Node):
121     def __init__(self, separator):
122         sep = separator.strip()
123         if sep[0] == sep[-1] and sep[0] in ('\'', '"'):
124             sep = sep[1:-1]
125         else:
126             raise template.TemplateSyntaxError('separator in joinitems tag must be quoted')
127         self.content = sep
128
129     def render(self, context):
130         return self.content
131
132 class BlockMediaUrlNode(template.Node):
133     def __init__(self, nodelist):
134         self.items = nodelist
135
136     def render(self, context):
137         prefix = '///' + settings.FORUM_SCRIPT_ALIAS + 'm/'
138         url = ''
139         if self.items:
140             url += '/'
141         for item in self.items:
142             url += item.render(context)
143
144         url = skins.find_media_source(url)
145         url = prefix + url
146         out = posixpath.normpath(url)
147         return out.replace(' ', '')
148
149 @register.tag(name='blockmedia')
150 def blockmedia(parser, token):
151     try:
152         tagname = token.split_contents()
153     except ValueError:
154         raise template.TemplateSyntaxError("blockmedia tag does not use arguments")
155     nodelist = []
156     while True:
157         nodelist.append(parser.parse(('endblockmedia')))
158         next = parser.next_token()
159         if next.contents == 'endblockmedia':
160             break
161     return BlockMediaUrlNode(nodelist)
162
163
164 @register.simple_tag
165 def fullmedia(url):
166     domain = settings.APP_URL
167     #protocol = getattr(settings, "PROTOCOL", "http")
168     path = media(url)
169     return "%s%s" % (domain, path)
170
171
172 class SimpleVarNode(template.Node):
173     def __init__(self, name, value):
174         self.name = name
175         self.value = template.Variable(value)
176
177     def render(self, context):
178         context[self.name] = self.value.resolve(context)
179         return ''
180
181 class BlockVarNode(template.Node):
182     def __init__(self, name, block):
183         self.name = name
184         self.block = block
185
186     def render(self, context):
187         source = self.block.render(context)
188         context[self.name] = source.strip()
189         return ''
190
191
192 @register.tag(name='var')
193 def do_var(parser, token):
194     tokens = token.split_contents()[1:]
195
196     if not len(tokens) or not re.match('^\w+$', tokens[0]):
197         raise template.TemplateSyntaxError("Expected variable name")
198
199     if len(tokens) == 1:
200         nodelist = parser.parse(('endvar',))
201         parser.delete_first_token()
202         return BlockVarNode(tokens[0], nodelist)
203     elif len(tokens) == 3:
204         return SimpleVarNode(tokens[0], tokens[2])
205
206     raise template.TemplateSyntaxError("Invalid number of arguments")
207
208 class DeclareNode(template.Node):
209     dec_re = re.compile('^\s*(\w+)\s*(:?=)\s*(.*)$')
210
211     def __init__(self, block):
212         self.block = block
213
214     def render(self, context):
215         source = self.block.render(context)
216
217         for line in source.splitlines():
218             m = self.dec_re.search(line)
219             if m:
220                 clist = list(context)
221                 clist.reverse()
222                 d = {}
223                 d['_'] = _
224                 d['os'] = os
225                 d['html'] = html
226                 d['reverse'] = reverse
227                 for c in clist:
228                     d.update(c)
229                 try:
230                     context[m.group(1).strip()] = eval(m.group(3).strip(), d)
231                 except Exception, e:
232                     logging.error("Error in declare tag, when evaluating: %s" % m.group(3).strip())
233                     raise
234         return ''
235
236 @register.tag(name='declare')
237 def do_declare(parser, token):
238     nodelist = parser.parse(('enddeclare',))
239     parser.delete_first_token()
240     return DeclareNode(nodelist)