diff --git a/server/apps/main/feeds.py b/server/apps/main/feeds.py new file mode 100644 index 00000000..1e499cb8 --- /dev/null +++ b/server/apps/main/feeds.py @@ -0,0 +1,59 @@ +from .models import PublicExperience +from django.contrib.syndication.views import Feed +from django.urls import reverse +from server.apps.main.helpers import extract_triggers_to_show, expand_filter +from django.utils.feedgenerator import Atom1Feed + +class PublicExperienceFeed(Feed): + description_template = "main/feed.html" + + def get_object(self, request): + # check if 'all triggers' is in keys + all_triggers = request.GET.get("all_triggers", False) + # set all trigger labels if set + if all_triggers: + allowed_triggers = { + "abuse", + "violence", + "drug", + "mentalhealth", + "negbody", + "other", + } + else: + # Check the allowed triggers + allowed_triggers = set(request.GET.keys()) + triggers_to_show = extract_triggers_to_show(allowed_triggers) + return triggers_to_show + + def title(self, obj): + return "AutSPACEs public experiences" + + def link(self, obj): + return reverse("main:public_experiences") + + def description(self, obj): + joined_triggers = ", ".join(obj) + if joined_triggers: + return "This feed includes potentially triggering stories related to %s" % joined_triggers + else: + return "No triggering content is included in this feed" + + def item_link(self, item): + return reverse('main:single_story', args=[item.experience_id]) + + def item_title(self, item): + return item.title_text + + def item_pubdate(self, item): + return item.created_at + + def items(self, obj): + experiences = PublicExperience.objects.filter(moderation_status="approved") + experiences = expand_filter(experiences, obj) + experiences = experiences.order_by("-created_at")[:10] + return experiences + +class PublicExperienceAtomFeed(PublicExperienceFeed): + feed_type = Atom1Feed + subtitle = PublicExperienceFeed.description \ No newline at end of file diff --git a/server/apps/main/templates/main/application.html b/server/apps/main/templates/main/application.html index 7e33371c..0646f09f 100644 --- a/server/apps/main/templates/main/application.html +++ b/server/apps/main/templates/main/application.html @@ -26,6 +26,12 @@ {%block page_css%} {% endblock %} + + {% if rss_link %} + + + {% endif %} + diff --git a/server/apps/main/templates/main/experiences_page.html b/server/apps/main/templates/main/experiences_page.html index f829e5c8..5c0104ab 100644 --- a/server/apps/main/templates/main/experiences_page.html +++ b/server/apps/main/templates/main/experiences_page.html @@ -135,7 +135,6 @@

View Stories

- {% if searched %} @@ -144,8 +143,6 @@

View Stories

{% endif %} - -
{% for experience in experiences %} @@ -229,6 +226,8 @@

Recommendation

{% include 'main/pagination.html' with stories=experiences page_query_param='page' %} {% endif %} +
+ You can also subscribe to this page as a feed. The current trigger options will be preserved.
diff --git a/server/apps/main/templates/main/feed.html b/server/apps/main/templates/main/feed.html new file mode 100644 index 00000000..99aade63 --- /dev/null +++ b/server/apps/main/templates/main/feed.html @@ -0,0 +1,10 @@ + +

The experience

+

+{{ obj.experience_text }} +

+ +

What would make a difference

+

+ {{ obj.difference_text }} +

\ No newline at end of file diff --git a/server/apps/main/tests/test_views.py b/server/apps/main/tests/test_views.py index d9892c6f..49ac0ffc 100644 --- a/server/apps/main/tests/test_views.py +++ b/server/apps/main/tests/test_views.py @@ -804,3 +804,26 @@ def test_my_stories_pagination_page2(self): assert len(stories) == min(num_items_per_page, n_stories) # check story numbering assert stories[0]['number'] == num_items_per_page + 1 # first story on page 1 is continuation of page 1 + + + + def test_feeds(self): + c = Client() + c.force_login(self.user_a) + response = c.get("/main/public_experiences/rss.xml") + assert response.status_code == 200 + self.assertTemplateUsed(response, "main/feed.html") + # Check that there is only one story visible - the one with no triggering labels + self.assertContains(response,"No triggering content is included in this feed") + self.assertContains(response,"", count=1) + + # If you allow the abuse tag there should be 2 stories one with no tags one with the abuse tag + search_response_abuse = c.get("/main/public_experiences/rss.xml?abuse=True") + self.assertNotContains(search_response_abuse,"No triggering content is included in this feed") + self.assertContains(search_response_abuse,"", count=2) + + + search_response_t = c.get("/main/public_experiences/rss.xml?all_triggers=True") + self.assertContains(search_response_t,"", count=2) + + diff --git a/server/apps/main/urls.py b/server/apps/main/urls.py index 43e67b60..c38bec79 100644 --- a/server/apps/main/urls.py +++ b/server/apps/main/urls.py @@ -1,5 +1,6 @@ from django.urls import path, re_path from server.apps.main import views +from server.apps.main import feeds app_name = "main" @@ -33,4 +34,6 @@ path("registration/", views.registration, name="registration"), path("single_story//",views.single_story,name="single_story"), path("success_confirm/", views.success_confirm, name="success_confirm"), + path("public_experiences/rss.xml", feeds.PublicExperienceFeed(), name='rss_feed'), + path("public_experiences/atom.xml", feeds.PublicExperienceAtomFeed(), name='atom_feed'), ] diff --git a/server/apps/main/views.py b/server/apps/main/views.py index 983b34a1..c7488620 100644 --- a/server/apps/main/views.py +++ b/server/apps/main/views.py @@ -410,7 +410,10 @@ def list_public_experiences(request): exp_context = {"experiences": page_experiences} - context = {**tts, **exp_context, **search_context} + rss_link = reverse("main:rss_feed") + "?" + request.GET.urlencode() + atom_link = rss_link = reverse("main:atom_feed") + "?" + request.GET.urlencode() + + context = {'rss_link': rss_link, 'atom_link': atom_link, **tts, **exp_context, **search_context} # Standard page showing all moderated stories return render(request, "main/experiences_page.html", context=context)