diff --git a/publichealth/feedler/__init__.py b/publichealth/feedler/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/publichealth/feedler/apps.py b/publichealth/feedler/apps.py new file mode 100644 index 0000000..7bc8f1e --- /dev/null +++ b/publichealth/feedler/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class FeedlerConfig(AppConfig): + name = 'feedler' diff --git a/publichealth/feedler/migrations/0001_initial.py b/publichealth/feedler/migrations/0001_initial.py new file mode 100644 index 0000000..9fb3abd --- /dev/null +++ b/publichealth/feedler/migrations/0001_initial.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.3 on 2017-07-03 11:24 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('wagtailcore', '0040_merge_20170703_1238'), + ] + + operations = [ + migrations.CreateModel( + name='Entry', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('raw', models.TextField(blank=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('published', models.DateTimeField(auto_now_add=True)), + ('entry_id', models.IntegerField(blank=True)), + ('title', models.CharField(max_length=255)), + ('origin_title', models.CharField(blank=True, max_length=255)), + ('link', models.URLField()), + ('visual', models.URLField(blank=True)), + ('content', models.TextField()), + ('tags', models.TextField(blank=True)), + ], + options={ + 'verbose_name_plural': 'Entries', + }, + ), + migrations.CreateModel( + name='EntryCategory', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.CharField(max_length=255)), + ('feedly_id', models.CharField(max_length=200)), + ], + ), + migrations.CreateModel( + name='FeedlySettings', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('feedly_auth', models.TextField(blank=True, help_text='Your developer authorization key')), + ('feedly_pages', models.IntegerField(blank=True, choices=[(1, '2'), (2, '5'), (3, '10'), (4, '50')], help_text='How many pages to fetch?', null=True)), + ('feedly_stream', models.TextField(blank=True, help_text='Stream ID to fetch')), + ('site', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, to='wagtailcore.Site')), + ], + options={ + 'verbose_name': 'Feedly', + }, + ), + migrations.AddField( + model_name='entry', + name='categories', + field=models.ManyToManyField(blank=True, to='feedler.EntryCategory'), + ), + ] diff --git a/publichealth/feedler/migrations/__init__.py b/publichealth/feedler/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/publichealth/feedler/models/__init__.py b/publichealth/feedler/models/__init__.py new file mode 100644 index 0000000..012e5e5 --- /dev/null +++ b/publichealth/feedler/models/__init__.py @@ -0,0 +1,2 @@ +from .models import * +from .admin import * diff --git a/publichealth/feedler/models/admin.py b/publichealth/feedler/models/admin.py new file mode 100644 index 0000000..ed64f50 --- /dev/null +++ b/publichealth/feedler/models/admin.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +import requests, json, codecs + +from django.contrib import admin + +from django.db import models +from django.db.models.signals import pre_save +from django.dispatch import receiver +from django.core.mail import send_mail + +from wagtail.contrib.settings.models import BaseSetting, register_setting + +# Feedly integration module + +@register_setting +class FeedlySettings(BaseSetting): + feedly_auth = models.TextField( + help_text='Your developer authorization key', blank=True) + feedly_pages = models.IntegerField( + choices=( + (1, '2'), + (2, '5'), + (3, '10'), + (4, '50'), + ), blank=True, null=True, + help_text='How many pages to fetch?' + ) + feedly_stream = models.TextField( + help_text='Stream ID to fetch', blank=True) + class Meta: + verbose_name = 'Feedly' + +@receiver(pre_save, sender=FeedlySettings) +def handle_save_settings(sender, instance, *args, **kwargs): + if instance.feedly_stream and instance.feedly_auth: + entries = [] + url = 'https://cloud.feedly.com/v3/streams/contents?streamId=' + url = url + instance.feedly_stream + headers = { + 'Authorization': 'OAuth '+instance.feedly_auth + } + contents = requests.get(url, headers=headers).json() + if 'errorMessage' in contents: + raise PermissionError(contents['errorMessage']) + for raw_entry in contents['items']: + entry = Entry(raw_entry) + entries.append(entry) + print(json.dumps(entries)) diff --git a/publichealth/feedler/models/models.py b/publichealth/feedler/models/models.py new file mode 100644 index 0000000..223428a --- /dev/null +++ b/publichealth/feedler/models/models.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- + +from datetime import datetime + +from django.db import models + +class EntryCategory(models.Model): + """A structure for sorting through entry models + """ + label = models.CharField(max_length=255) + feedly_id = models.CharField(max_length=200) + +class Entry(models.Model): + """Implementation of the Entry from the feedly API as generic Django model + """ + raw = models.TextField(blank=True) + + updated = models.DateTimeField(auto_now=True) + published = models.DateTimeField(auto_now_add=True) + entry_id = models.IntegerField(blank=True) + + title = models.CharField(max_length=255) + origin_title = models.CharField(max_length=255, blank=True) + link = models.URLField() + visual = models.URLField(blank=True) + + content = models.TextField() + tags = models.TextField(blank=True) + + categories = models.ManyToManyField(EntryCategory, blank=True) + + class Meta: + verbose_name_plural = 'Entries' + + def _buildInstance(self, raw): + """ + Parse the raw JSON implementation from the Feedly API + """ + self.raw = raw + + self.published = datetime.utcfromtimestamp(raw['published']) + self.entry_id = raw['id'] + + self.title = raw['title'] + self.origin_title = raw['origin']['title'] + self.link = raw['alternate'][0]['href'] + self.visual = raw['visual']['url'] + + self._buildContent() + + # if 'categories' in raw: + # self.categories = raw['categories'] + # else: + # self.categories = [] + + def _buildContent(self): + # Collect text content + if 'content' in self.raw: + self.content = self.raw['content'] + else: + if 'summary' in self.raw: + self.content = self.raw['summary'] + else: + self.content = '' + # Collect tags + tags = [] + for tag in self.raw['tags']: + if 'label' in tag: + tags.push(tag['label'].replace(',','-')) + self.tags = ','.join('tags') diff --git a/publichealth/feedler/tests.py b/publichealth/feedler/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/publichealth/feedler/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/publichealth/feedler/views.py b/publichealth/feedler/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/publichealth/feedler/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/publichealth/feedler/wagtail_hooks.py b/publichealth/feedler/wagtail_hooks.py new file mode 100644 index 0000000..8d1797a --- /dev/null +++ b/publichealth/feedler/wagtail_hooks.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- + +from wagtail.contrib.modeladmin.options import ( + ModelAdmin, modeladmin_register) + +from .models import Entry + +class EntryModelAdmin(ModelAdmin): + model = Entry + menu_icon = 'date' + menu_order = 200 + add_to_settings_menu = False + exclude_from_explorer = True + list_display = ('updated', 'title', 'origin_title', 'tags') + # list_filter = ('origin_title') + # search_fields = ('title', 'origin_title', 'content', 'tags') + +modeladmin_register(EntryModelAdmin)