93 lines
2.9 KiB
Python
93 lines
2.9 KiB
Python
import hashlib
|
|
import datetime
|
|
import logging
|
|
|
|
from django.db import models
|
|
from django.conf import settings
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.utils.html import strip_tags
|
|
from django.core.cache import cache
|
|
|
|
import feedparser
|
|
|
|
from cms.models import CMSPlugin
|
|
|
|
from . import utils
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
FEED_CACHE_TIMEOUT = 86400 # 1 week
|
|
|
|
class FeedPreference(models.Model):
|
|
user = models.ForeignKey(settings.AUTH_USER_MODEL)
|
|
feed = models.ForeignKey('Feed')
|
|
|
|
class Meta:
|
|
verbose_name = _('user feed subscription')
|
|
verbose_name_plural = _('user feed subscriptions')
|
|
|
|
class SelectUserFeed(CMSPlugin):
|
|
pass
|
|
|
|
class ShowUserFeed(CMSPlugin):
|
|
limit = models.PositiveIntegerField(default=10)
|
|
timeout = models.PositiveIntegerField(default=60)
|
|
|
|
class Feed(models.Model):
|
|
name = models.CharField(max_length=32, verbose_name=_('name'))
|
|
url = models.URLField()
|
|
color_hex = models.CharField(max_length=6,
|
|
verbose_name=_('Color'),
|
|
help_text=_('as an hexadecimal number'),
|
|
blank=True)
|
|
css_classes = models.CharField(max_length=128,
|
|
verbose_name=_('CSS classes'),
|
|
blank=True)
|
|
|
|
def load(self, now=None, limit=9999):
|
|
if now is None:
|
|
now = datetime.datetime.utcnow()
|
|
feed = feedparser.parse(self.url)
|
|
key = self.cache_key()
|
|
entries = []
|
|
for entry in feed.entries:
|
|
for attribute in ('published_parsed', 'updated_parsed',
|
|
'created_parsed', 'expired_parsed'):
|
|
date = getattr(entry, attribute, None)
|
|
if date is not None:
|
|
break
|
|
if date is None:
|
|
continue
|
|
title = strip_tags(entry.title.strip())
|
|
if not title:
|
|
title = strip_tags(entry.description.strip())
|
|
title = ' '.join(title.split(' ')[:30])
|
|
if not title:
|
|
continue
|
|
entries.append((date, title, entry.link))
|
|
entries.sort(reverse=True)
|
|
entries = entries[:limit]
|
|
cache.set(key, (entries, now), FEED_CACHE_TIMEOUT)
|
|
duration = datetime.datetime.utcnow()-now
|
|
logger.debug('loaded RSS feed %r in %s seconds', self.url, duration.seconds)
|
|
return entries
|
|
|
|
def cache_key(self):
|
|
return hashlib.md5(self.url).hexdigest()
|
|
|
|
def get_feed_entries(self, limit=10, timeout=3600):
|
|
key = self.cache_key()
|
|
now = datetime.datetime.utcnow()
|
|
entries, stamp = cache.get(key, (None, None))
|
|
if entries is None or now-stamp > datetime.timedelta(seconds=timeout):
|
|
utils.launch_in_thread(key, self.load, now, limit)
|
|
return entries
|
|
|
|
|
|
class Meta:
|
|
verbose_name = _('feed')
|
|
verbose_name_plural = _('feeds')
|
|
|
|
def __unicode__(self):
|
|
return self.name
|