~widelands-dev/widelands-website/trunk

22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
1
from datetime import datetime
274 by Holger Rapp
Disable wikiwords in the forums
2
from mainpage.templatetags.wl_markdown import do_wl_markdown
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
3
import os.path
254 by Holger Rapp
Fixed a few deprecation warnings and reparied cross site scripting fixes for AJAX requests
4
import hashlib
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
5
6
from django.db import models
7
from django.contrib.auth.models import User
8
from django.core.urlresolvers import reverse
9
from django.utils.html import strip_tags
10
from django.utils.translation import ugettext_lazy as _
11
from django.conf import settings
12
192 by Holger Rapp
Trying to fix 338756
13
from pybb.markups import mypostmarkup
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
14
from pybb.util import urlize, memoize_method, unescape
15
from pybb import settings as pybb_settings
90 by Holger Rapp
Sphinx must now be enabled in local_settings.py, otherwise it won't work
16
17
from django.conf import settings
18
if settings.USE_SPHINX:
257 by Holger Rapp
Fixed deprecation in SphinxSearch
19
    from djangosphinx.models import SphinxSearch
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
20
209.1.21 by Timo Wingender
Add notifications to forum
21
try:
22
    from notification import models as notification
23
    from django.db.models import signals
24
except ImportError:
25
    notification = None
26
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
27
MARKUP_CHOICES = (
28
    ('markdown', 'markdown'),
209.1.68 by Timo Wingender
add field to choose between markdown and bbcode as markup
29
    ('bbcode', 'bbcode'),
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
30
)
31
32
33
class Category(models.Model):
34
    name = models.CharField(_('Name'), max_length=80)
35
    position = models.IntegerField(_('Position'), blank=True, default=0)
36
37
    class Meta:
38
        ordering = ['position']
39
        verbose_name = _('Category')
40
        verbose_name_plural = _('Categories')
41
42
    def __unicode__(self):
43
        return self.name
44
45
    def forum_count(self):
46
        return self.forums.all().count()
47
48
    def get_absolute_url(self):
49
        return reverse('pybb_category', args=[self.id])
50
51
    @property
52
    def topics(self):
53
        return Topic.objects.filter(forum__category=self).select_related()
192 by Holger Rapp
Trying to fix 338756
54
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
55
    @property
56
    def posts(self):
57
        return Post.objects.filter(topic__forum__category=self).select_related()
58
59
60
class Forum(models.Model):
61
    category = models.ForeignKey(Category, related_name='forums', verbose_name=_('Category'))
62
    name = models.CharField(_('Name'), max_length=80)
63
    position = models.IntegerField(_('Position'), blank=True, default=0)
64
    description = models.TextField(_('Description'), blank=True, default='')
65
    moderators = models.ManyToManyField(User, blank=True, null=True, verbose_name=_('Moderators'))
66
    updated = models.DateTimeField(_('Updated'), null=True)
67
68
    class Meta:
69
        ordering = ['position']
70
        verbose_name = _('Forum')
71
        verbose_name_plural = _('Forums')
72
73
    def __unicode__(self):
74
        return self.name
75
76
    def topic_count(self):
77
        return self.topics.all().count()
78
79
    def get_absolute_url(self):
80
        return reverse('pybb_forum', args=[self.id])
192 by Holger Rapp
Trying to fix 338756
81
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
82
    @property
83
    def posts(self):
84
        return Post.objects.filter(topic__forum=self).select_related()
85
86
    @property
323 by Holger Rapp
Let post count be calculated automatically instead of keeping track of it manually. Let's see how this affects performance
87
    def post_count(self):
88
        return Post.objects.filter(topic__forum=self).count()
89
90
    @property
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
91
    def last_post(self):
92
        posts = self.posts.order_by('-created').select_related()
93
        try:
94
            return posts[0]
95
        except IndexError:
96
            return None
97
98
99
class Topic(models.Model):
100
    forum = models.ForeignKey(Forum, related_name='topics', verbose_name=_('Forum'))
101
    name = models.CharField(_('Subject'), max_length=255)
102
    created = models.DateTimeField(_('Created'), null=True)
103
    updated = models.DateTimeField(_('Updated'), null=True)
104
    user = models.ForeignKey(User, verbose_name=_('User'))
105
    views = models.IntegerField(_('Views count'), blank=True, default=0)
106
    sticky = models.BooleanField(_('Sticky'), blank=True, default=False)
107
    closed = models.BooleanField(_('Closed'), blank=True, default=False)
108
    subscribers = models.ManyToManyField(User, related_name='subscriptions', verbose_name=_('Subscribers'), blank=True)
192 by Holger Rapp
Trying to fix 338756
109
110
    # Django sphinx
90 by Holger Rapp
Sphinx must now be enabled in local_settings.py, otherwise it won't work
111
    if settings.USE_SPHINX:
112
        search = SphinxSearch(
113
            weights = {
114
                'name': 100,
115
                }
116
            )
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
117
118
    class Meta:
192 by Holger Rapp
Trying to fix 338756
119
        ordering = ['-updated']
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
120
        verbose_name = _('Topic')
121
        verbose_name_plural = _('Topics')
122
123
    def __unicode__(self):
124
        return self.name
192 by Holger Rapp
Trying to fix 338756
125
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
126
    @property
127
    def head(self):
128
        return self.posts.all().order_by('created').select_related()[0]
129
130
    @property
131
    def last_post(self):
132
        return self.posts.all().order_by('-created').select_related()[0]
133
323 by Holger Rapp
Let post count be calculated automatically instead of keeping track of it manually. Let's see how this affects performance
134
    @property
135
    def post_count(self):
136
        return Post.objects.filter(topic=self).count()
137
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
138
    def get_absolute_url(self):
139
        return reverse('pybb_topic', args=[self.id])
140
141
    def save(self, *args, **kwargs):
209.1.21 by Timo Wingender
Add notifications to forum
142
        new = self.id is None
143
        if new:
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
144
            self.created = datetime.now()
145
        super(Topic, self).save(*args, **kwargs)
146
147
    def update_read(self, user):
148
        read, new = Read.objects.get_or_create(user=user, topic=self)
149
        if not new:
150
            read.time = datetime.now()
151
            read.save()
152
153
    #def has_unreads(self, user):
154
        #try:
155
            #read = Read.objects.get(user=user, topic=self)
156
        #except Read.DoesNotExist:
157
            #return True
158
        #else:
159
            #return self.updated > read.time
160
161
162
class RenderableItem(models.Model):
163
    """
164
    Base class for models that has markup, body, body_text and body_html fields.
165
    """
166
167
    class Meta:
168
        abstract = True
169
170
    def render(self):
171
        if self.markup == 'bbcode':
172
            self.body_html = mypostmarkup.markup(self.body, auto_urls=False)
173
        elif self.markup == 'markdown':
274 by Holger Rapp
Disable wikiwords in the forums
174
            self.body_html = unicode(do_wl_markdown(self.body, safe_mode='escape', wikiwords=False))
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
175
        else:
176
            raise Exception('Invalid markup property: %s' % self.markup)
177
178
        # Remove tags which was generated with the markup processor
179
        text = strip_tags(self.body_html)
180
181
        # Unescape entities which was generated with the markup processor
182
        self.body_text = unescape(text)
183
184
        self.body_html = urlize(self.body_html)
185
186
187
class Post(RenderableItem):
188
    topic = models.ForeignKey(Topic, related_name='posts', verbose_name=_('Topic'))
189
    user = models.ForeignKey(User, related_name='posts', verbose_name=_('User'))
190
    created = models.DateTimeField(_('Created'), blank=True)
191
    updated = models.DateTimeField(_('Updated'), blank=True, null=True)
192
    markup = models.CharField(_('Markup'), max_length=15, default=pybb_settings.DEFAULT_MARKUP, choices=MARKUP_CHOICES)
193
    body = models.TextField(_('Message'))
194
    body_html = models.TextField(_('HTML version'))
195
    body_text = models.TextField(_('Text version'))
196
    user_ip = models.IPAddressField(_('User IP'), blank=True, default='')
192 by Holger Rapp
Trying to fix 338756
197
198
    # Django sphinx
90 by Holger Rapp
Sphinx must now be enabled in local_settings.py, otherwise it won't work
199
    if settings.USE_SPHINX:
200
        search = SphinxSearch(
201
            weights = {
202
                'body_text': 100,
203
                'body_html': 0,
204
                }
205
            )
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
206
207
208
    class Meta:
209
        ordering = ['created']
210
        verbose_name = _('Post')
211
        verbose_name_plural = _('Posts')
212
213
    def summary(self):
214
        LIMIT = 50
192 by Holger Rapp
Trying to fix 338756
215
        tail = len(self.body) > LIMIT and '...' or ''
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
216
        return self.body[:LIMIT] + tail
217
218
    __unicode__ = summary
219
220
    def save(self, *args, **kwargs):
221
        if self.created is None:
222
            self.created = datetime.now()
209.1.21 by Timo Wingender
Add notifications to forum
223
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
224
        self.render()
225
226
        new = self.id is None
227
228
        if new:
229
            self.topic.updated = datetime.now()
230
            self.topic.save()
231
            self.topic.forum.updated = self.topic.updated
232
            self.topic.forum.save()
233
234
        super(Post, self).save(*args, **kwargs)
235
236
237
    def get_absolute_url(self):
238
        return reverse('pybb_post', args=[self.id])
239
240
241
    def delete(self, *args, **kwargs):
242
        self_id = self.id
243
        head_post_id = self.topic.posts.order_by('created')[0].id
244
        super(Post, self).delete(*args, **kwargs)
245
246
        self.topic.save()
247
        self.topic.forum.save()
248
249
        if self_id == head_post_id:
250
            self.topic.delete()
251
252
253
class Read(models.Model):
254
    """
192 by Holger Rapp
Trying to fix 338756
255
    For each topic that user has entered the time
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
256
    is logged to this model.
257
    """
258
259
    user = models.ForeignKey(User, verbose_name=_('User'))
260
    topic = models.ForeignKey(Topic, verbose_name=_('Topic'))
261
    time = models.DateTimeField(_('Time'), blank=True)
262
263
    class Meta:
264
        unique_together = ['user', 'topic']
265
        verbose_name = _('Read')
266
        verbose_name_plural = _('Reads')
267
268
    def save(self, *args, **kwargs):
269
        if self.time is None:
270
            self.time = datetime.now()
271
        super(Read, self).save(*args, **kwargs)
272
273
274
    def __unicode__(self):
275
        return u'T[%d], U[%d]: %s' % (self.topic.id, self.user.id, unicode(self.time))
276
277
278
class PrivateMessage(RenderableItem):
279
280
    dst_user = models.ForeignKey(User, verbose_name=_('Recipient'), related_name='dst_users')
281
    src_user = models.ForeignKey(User, verbose_name=_('Author'), related_name='src_users')
282
    read = models.BooleanField(_('Read'), blank=True, default=False)
283
    created = models.DateTimeField(_('Created'), blank=True)
284
    markup = models.CharField(_('Markup'), max_length=15, default=pybb_settings.DEFAULT_MARKUP, choices=MARKUP_CHOICES)
285
    subject = models.CharField(_('Subject'), max_length=255)
286
    body = models.TextField(_('Message'))
287
    body_html = models.TextField(_('HTML version'))
288
    body_text = models.TextField(_('Text version'))
289
290
    class Meta:
291
        ordering = ['-created']
292
        verbose_name = _('Private message')
293
        verbose_name_plural = _('Private messages')
294
295
    # TODO: summary and part of the save method is the same as in the Post model
296
    # move to common functions
297
    def summary(self):
298
        LIMIT = 50
192 by Holger Rapp
Trying to fix 338756
299
        tail = len(self.body) > LIMIT and '...' or ''
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
300
        return self.body[:LIMIT] + tail
301
302
    def __unicode__(self):
303
        return self.subject
304
305
    def save(self, *args, **kwargs):
306
        if self.created is None:
307
            self.created = datetime.now()
308
        self.render()
309
310
        new = self.id is None
311
        super(PrivateMessage, self).save(*args, **kwargs)
312
313
    def get_absolute_url(self):
314
        return  reverse('pybb_show_pm', args=[self.id])
315
316
317
class Attachment(models.Model):
318
    post = models.ForeignKey(Post, verbose_name=_('Post'), related_name='attachments')
319
    size = models.IntegerField(_('Size'))
320
    content_type = models.CharField(_('Content type'), max_length=255)
321
    path = models.CharField(_('Path'), max_length=255)
322
    name = models.TextField(_('Name'))
323
    hash = models.CharField(_('Hash'), max_length=40, blank=True, default='', db_index=True)
324
325
    def save(self, *args, **kwargs):
326
        super(Attachment, self).save(*args, **kwargs)
327
        if not self.hash:
254 by Holger Rapp
Fixed a few deprecation warnings and reparied cross site scripting fixes for AJAX requests
328
            self.hash = hashlib.sha1(str(self.id) + settings.SECRET_KEY).hexdigest()
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
329
        super(Attachment, self).save(*args, **kwargs)
330
331
    def __unicode__(self):
332
        return self.name
333
334
    def get_absolute_url(self):
335
        return reverse('pybb_attachment', args=[self.hash])
336
337
    def size_display(self):
338
        size = self.size
339
        if size < 1024:
340
            return '%b' % size
341
        elif size < 1024 * 1024:
342
            return '%dKb' % int(size / 1024)
343
        else:
344
            return '%.2fMb' % (size / float(1024 * 1024))
345
346
347
    def get_absolute_path(self):
348
        return os.path.join(settings.MEDIA_ROOT, pybb_settings.ATTACHMENT_UPLOAD_TO,
349
                            self.path)
350
351
209.1.21 by Timo Wingender
Add notifications to forum
352
#if notification is not None:
353
#    signals.post_save.connect(notification.handle_observations, sender=Post)
354
22 by Holger Rapp
- Added my hacked version of pybb. Remerging new versions is very difficult at this point :(
355
from pybb import signals
356
signals.setup_signals()