Permalink
Browse files

commit inicial

  • Loading branch information...
0 parents commit 959648e37744484de92e86ca3941bc6a139ccebd @flmendes committed Apr 14, 2011
@@ -0,0 +1,4 @@
+.DS_Store?
+.DS_Store
+
+*.pyc
3 README
@@ -0,0 +1,3 @@
+Agregador de feeds, que faz parte do site http://djangobrasil.org
+
+https://github.com/djangobrasil/djangobrasil.org
@@ -0,0 +1,27 @@
+Copyright (c) 2005, the Lawrence Journal-World
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of Django nor the names of its contributors may be used
+ to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
No changes.
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2005, the Lawrence Journal-World
+# All rights reserved.
+#
+# See LICENSE file in src/djangobrasil/apps/aggregator/ directory.
+#
+
+from django.contrib.admin.options import ModelAdmin
+from django.contrib import admin
+from djangobrasil.apps.aggregator.models import Feed
+
+class FeedAdmin(ModelAdmin):
+ list_display = ("title", "public_url", "is_defunct")
+ list_filter = ("is_defunct",)
+ ordering = ("title",)
+ search_fields = ("title", "public_url")
+ list_per_page = 500
+
+admin.site.register(Feed, FeedAdmin)
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2005, the Lawrence Journal-World
+# All rights reserved.
+#
+# See LICENSE file in src/djangobrasil/apps/aggregator/ directory.
+#
+
+
+"""
+Mark people with 404'ing feeds as defunct.
+"""
+
+for f in Feed.objects.all():
+ try:
+ r = urllib2.urlopen(f.feed_url)
+ except urllib2.HTTPError, e:
+ if e.code == 404 or e.code == 500:
+ print "%s on %s; marking defunct" % (e.code, f)
+ f.is_defunct = True
+ f.save()
+ else:
+ raise
@@ -0,0 +1,84 @@
+#
+# Copyright (c) 2005, the Lawrence Journal-World
+# All rights reserved.
+#
+# See LICENSE file in src/djangobrasil/apps/aggregator/ directory.
+#
+
+
+"""
+Update feeds for Django community page. Requires Mark Pilgrim's excellent
+Universal Feed Parser (http://feedparser.org)
+"""
+
+import os
+import sys
+import time
+import socket
+import optparse
+import datetime
+import feedparser
+
+LOCKFILE = "/tmp/update_feeds.lock"
+def update_feeds(verbose=False):
+ from djangobrasil.apps.aggregator.models import Feed, FeedItem
+ for feed in Feed.objects.filter(is_defunct=False):
+ if verbose:
+ print feed
+ parsed_feed = feedparser.parse(feed.feed_url)
+ for entry in parsed_feed.entries:
+ title = entry.title.encode(parsed_feed.encoding, "xmlcharrefreplace")
+ guid = entry.get("id", entry.link).encode(parsed_feed.encoding, "xmlcharrefreplace")
+ link = entry.link.encode(parsed_feed.encoding, "xmlcharrefreplace")
+
+ if not guid:
+ guid = link
+
+ if hasattr(entry, "summary"):
+ content = entry.summary
+ elif hasattr(entry, "content"):
+ content = entry.content[0].value
+ elif hasattr(entry, "description"):
+ content = entry.description
+ else:
+ content = u""
+ content = content.encode(parsed_feed.encoding, "xmlcharrefreplace")
+
+ try:
+ if entry.has_key('modified_parsed'):
+ date_modified = datetime.datetime.fromtimestamp(time.mktime(entry.modified_parsed))
+ elif parsed_feed.feed.has_key('modified_parsed'):
+ date_modified = datetime.datetime.fromtimestamp(time.mktime(parsed_feed.feed.modified_parsed))
+ elif parsed_feed.has_key('modified'):
+ date_modified = datetime.datetime.fromtimestamp(time.mktime(parsed_feed.modified))
+ else:
+ date_modified = datetime.datetime.now()
+ except TypeError:
+ date_modified = datetime.datetime.now()
+
+ try:
+ feed.feeditem_set.get(guid=guid)
+ except FeedItem.DoesNotExist:
+ feed.feeditem_set.create(title=title, link=link, summary=content, guid=guid, date_modified=date_modified)
+
+def main(argv):
+ socket.setdefaulttimeout(15)
+ parser = optparse.OptionParser()
+ parser.add_option('--settings')
+ parser.add_option('-v', '--verbose', action="store_true")
+ options, args = parser.parse_args(argv)
+ if options.settings:
+ os.environ["DJANGO_SETTINGS_MODULE"] = options.settings
+ update_feeds(options.verbose)
+
+if __name__ == '__main__':
+ try:
+ lockfile = os.open(LOCKFILE, os.O_CREAT | os.O_EXCL)
+ except OSError:
+ sys.exit(0)
+
+ try:
+ sys.exit(main(sys.argv))
+ finally:
+ os.close(lockfile)
+ os.unlink(LOCKFILE)
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2005, the Lawrence Journal-World
+# All rights reserved.
+#
+# See LICENSE file in src/djangobrasil/apps/aggregator/ directory.
+#
+
+from django.contrib.syndication.feeds import Feed
+from django.utils.feedgenerator import Atom1Feed
+from djangobrasil.apps.aggregator.models import FeedItem
+
+
+class RssCommunityAggregatorFeed(Feed):
+ title = u"Feeds da comunidade Django Brasil"
+ link = u"http://www.djangobrasil.org/comunidade/"
+ description = u"Agregador de feeds da comunidade Django Brasil."
+
+ def items(self):
+ return FeedItem.objects.all()[:15]
+
+class AtomCommunityAggregatorFeed(RssCommunityAggregatorFeed):
+ feed_type = Atom1Feed
+ subtitle = u"Agregador de feeds da comunidade Django Brasil"
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2005, the Lawrence Journal-World
+# All rights reserved.
+#
+# See LICENSE file in src/djangobrasil/apps/aggregator/ directory.
+#
+
+from django.db import models
+
+class Feed(models.Model):
+ title = models.CharField(max_length=500)
+ feed_url = models.URLField(unique=True, max_length=500)
+ public_url = models.URLField(max_length=500)
+ is_defunct = models.BooleanField()
+
+ class Meta:
+ db_table = 'aggregator_feeds'
+
+ def __unicode__(self):
+ return unicode(self.title)
+
+class FeedItem(models.Model):
+ feed = models.ForeignKey(Feed)
+ title = models.CharField(max_length=500)
+ link = models.URLField(max_length=500)
+ summary = models.TextField(blank=True)
+ date_modified = models.DateTimeField()
+ guid = models.CharField(max_length=500, unique=True, db_index=True)
+
+ class Meta:
+ db_table = 'aggregator_feeditems'
+ ordering = ("-date_modified",)
+
+ def __unicode__(self):
+ return self.title
+
+ def get_absolute_url(self):
+ return self.link
No changes.
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2005, the Lawrence Journal-World
+# All rights reserved.
+#
+# See LICENSE file in src/djangobrasil/apps/aggregator/ directory.
+#
+
+
+from django import template
+from djangobrasil.apps.aggregator.models import Feed
+
+class FeedListNode(template.Node):
+ def __init__(self, varname):
+ self.varname = varname
+
+ def render(self, context):
+ context[self.varname] = Feed.objects.filter(is_defunct=False).order_by('title')
+ return ''
+
+def do_get_feed_list(parser, token):
+ """
+ {% get_feed_list as feed_list %}
+ """
+ bits = token.contents.split()
+ if len(bits) != 3:
+ raise template.TemplateSyntaxError, "'%s' tag takes two arguments" % bits[0]
+ if bits[1] != "as":
+ raise template.TemplateSyntaxError, "First argument to '%s' tag must be 'as'" % bits[0]
+ return FeedListNode(bits[2])
+
+register = template.Library()
+register.tag('get_feed_list', do_get_feed_list)
@@ -0,0 +1,35 @@
+from unittest import TestCase
+from django.template import Template, Context
+from djangobrasil.apps.aggregator.models import Feed
+
+class FeedListTagTest(TestCase):
+
+ def setUp(self):
+ Feed.objects.create(
+ title='Igor',
+ feed_url='http://www.igorsobreira.com/feeds/categoria/django/',
+ public_url='http://www.igorsobreira.com/',
+ is_defunct=False,
+ )
+ Feed.objects.create(
+ title='Enrico',
+ feed_url='http://ricobl.wordpress.com/category/django/feed/',
+ public_url='http://ricobl.wordpress.com/',
+ is_defunct=False,
+ )
+ Feed.objects.create(
+ title='Andrews',
+ feed_url='http://www.andrewsmedina.com/rss/',
+ public_url='http://www.andrewsmedina.com/',
+ is_defunct=False,
+ )
+
+ def test_feed_list_should_be_in_alphabetical_order(self):
+ html = u"{% load aggregator %}"
+ html += u"{% get_feed_list as feed_list %}"
+ html += u"{% for feed in feed_list %}{{ feed }},{% endfor %}"
+
+ result = Template(html).render(Context({}))
+
+ self.assertEquals(u"Andrews,Enrico,Igor,", result)
+

0 comments on commit 959648e

Please sign in to comment.