diff options
Diffstat (limited to 'gstudio/management/commands/feed2gstudio.py')
-rw-r--r-- | gstudio/management/commands/feed2gstudio.py | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/gstudio/management/commands/feed2gstudio.py b/gstudio/management/commands/feed2gstudio.py new file mode 100644 index 00000000..dd1d3d26 --- /dev/null +++ b/gstudio/management/commands/feed2gstudio.py @@ -0,0 +1,209 @@ +# Copyright (c) 2011, 2012 Free Software Foundation + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +# This project incorporates work covered by the following copyright and permission notice: + +# Copyright (c) 2009, Julien Fache +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: + +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of the author nor the names of other +# 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. + +# Copyright (c) 2011, 2012 Free Software Foundation + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +"""Feed to Gstudio command module""" +import sys +from datetime import datetime +from optparse import make_option + +from django.utils.html import strip_tags +from django.db.utils import IntegrityError +from django.utils.encoding import smart_str +from django.contrib.auth.models import User +from django.contrib.sites.models import Site +from django.utils.text import truncate_words +from django.template.defaultfilters import slugify +from django.core.management.base import CommandError +from django.core.management.base import LabelCommand + +from gstudio import __version__ +from gstudio.models import Nodetype +from gstudio.models import Metatype +from gstudio.managers import PUBLISHED +from gstudio.signals import disconnect_gstudio_signals + + +class Command(LabelCommand): + """Command object for importing a RSS or Atom + feed into Gstudio.""" + help = 'Import a RSS or Atom feed into Gstudio.' + label = 'feed url' + args = 'url' + + option_list = LabelCommand.option_list + ( + make_option('--noautoexcerpt', action='store_false', + dest='auto_excerpt', default=True, + help='Do NOT generate an excerpt if not present.'), + make_option('--author', dest='author', default='', + help='All imported nodetypes belong to specified author'), + make_option('--metatype-is-tag', action='store_true', + dest='metatype-tag', default=False, + help='Store metatypes as tags'), + ) + SITE = Site.objects.get_current() + + def __init__(self): + """Init the Command and add custom styles""" + super(Command, self).__init__() + self.style.TITLE = self.style.SQL_FIELD + self.style.STEP = self.style.SQL_COLTYPE + self.style.ITEM = self.style.HTTP_INFO + disconnect_gstudio_signals() + + def write_out(self, message, verbosity_level=1): + """Convenient method for outputing""" + if self.verbosity and self.verbosity >= verbosity_level: + sys.stdout.write(smart_str(message)) + sys.stdout.flush() + + def handle_label(self, url, **options): + try: + import feedparser + except ImportError: + raise CommandError('You need to install the feedparser ' \ + 'module to run this command.') + + self.verbosity = int(options.get('verbosity', 1)) + self.auto_excerpt = options.get('auto_excerpt', True) + self.default_author = options.get('author') + self.metatype_tag = options.get('metatype-tag', False) + if self.default_author: + try: + self.default_author = User.objects.get( + username=self.default_author) + except User.DoesNotExist: + raise CommandError('Invalid username for default author') + + self.write_out(self.style.TITLE( + 'Starting importation of %s to Gstudio %s:\n' % (url, __version__))) + + feed = feedparser.parse(url) + self.import_nodetypes(feed.nodetypes) + + def import_nodetypes(self, feed_nodetypes): + """Import nodetypes""" + for feed_nodetype in feed_nodetypes: + self.write_out('> %s... ' % feed_nodetype.title) + creation_date = datetime(*feed_nodetype.date_parsed[:6]) + slug = slugify(feed_nodetype.title)[:255] + + if Nodetype.objects.filter(creation_date__year=creation_date.year, + creation_date__month=creation_date.month, + creation_date__day=creation_date.day, + slug=slug): + self.write_out(self.style.NOTICE( + 'SKIPPED (already imported)\n')) + continue + + metatypes = self.import_metatypes(feed_nodetype) + nodetype_dict = {'title': feed_nodetype.title[:255], + 'content': feed_nodetype.description, + 'excerpt': feed_nodetype.get('summary'), + 'status': PUBLISHED, + 'creation_date': creation_date, + 'start_publication': creation_date, + 'last_update': datetime.now(), + 'slug': slug} + + if not nodetype_dict['excerpt'] and self.auto_excerpt: + nodetype_dict['excerpt'] = truncate_words( + strip_tags(feed_nodetype.description), 50) + if self.metatype_tag: + nodetype_dict['tags'] = self.import_tags(metatypes) + + nodetype = Nodetype(**nodetype_dict) + nodetype.save() + nodetype.metatypes.add(*metatypes) + nodetype.sites.add(self.SITE) + + if self.default_author: + nodetype.authors.add(self.default_author) + elif feed_nodetype.get('author_detail'): + try: + user = User.objects.create_user( + slugify(feed_nodetype.author_detail.get('name')), + feed_nodetype.author_detail.get('email', '')) + except IntegrityError: + user = User.objects.get( + username=slugify(feed_nodetype.author_detail.get('name'))) + nodetype.authors.add(user) + + self.write_out(self.style.ITEM('OK\n')) + + def import_metatypes(self, feed_nodetype): + metatypes = [] + for cat in feed_nodetype.get('tags', ''): + metatype, created = Metatype.objects.get_or_create( + slug=slugify(cat.term), defaults={'title': cat.term}) + metatypes.append(metatype) + return metatypes + + def import_tags(self, metatypes): + tags = [] + for cat in metatypes: + if len(cat.title.split()) > 1: + tags.append('"%s"' % slugify(cat.title).replace('-', ' ')) + else: + tags.append(slugify(cat.title).replace('-', ' ')) + return ', '.join(tags) |