Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Rewrite community feed as Feed class #7254

Merged
merged 3 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions ietf/community/feeds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# Copyright The IETF Trust 2024, All Rights Reserved
# -*- coding: utf-8 -*-

import datetime
import uuid

import debug # pyflakes:ignore

from django.contrib.syndication.views import Feed
from django.http import HttpResponse
from django.utils import timezone
from django.utils.feedgenerator import Atom1Feed

from ietf.community.utils import states_of_significant_change
from ietf.community.views import lookup_community_list, MultiplePersonError
from ietf.doc.models import DocEvent

class Atom1WithNamespacesFeed(Atom1Feed):
def root_attributes(self):
attrs = super(Atom1WithNamespacesFeed, self).root_attributes()
attrs["xmlns:ietf"] = "http://ietf.org/atom/datatracker/community"
return attrs

def add_item_elements(self, handler, item):
super(Atom1WithNamespacesFeed, self).add_item_elements(handler, item)

for element_name in [
"type",
"stream",
"group",
"shepherd",
"ad",
"abstract",
"version",
]:
ietf_item_name = "ietf_%s" % element_name
ietf_element_name = "ietf:%s" % element_name
if ietf_item_name in item and item[ietf_item_name] is not None:
handler.addQuickElement(ietf_element_name, item[ietf_item_name])

if "ietf_state" in item and item["ietf_state"] is not None:
for state in item["ietf_state"]:
handler.addQuickElement("ietf:state", state["value"], {"type": state["type"]})

if "ietf_tag" in item and item["ietf_tag"] is not None:
for tag in item["ietf_tag"]:
handler.addQuickElement("ietf:tag", tag)

class CommunityFeed(Feed):
feed_type = Atom1WithNamespacesFeed

def __call__(self, request, *args, **kwargs):
try:
return super(CommunityFeed, self).__call__(request, *args, **kwargs)
except MultiplePersonError as err:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is no longer raised in this codepath

return HttpResponse(str(err), status=300)

def get_object(self, request, *args, **kwargs):
email_or_name = kwargs["email_or_name"]
acronym = kwargs["acronym"]
clist = lookup_community_list(request, email_or_name, acronym)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can now return 404

self.significant = request.GET.get('significant', '') == '1'
self.host = request.get_host()
self.feed_url = 'https://%s%s' % (self.host, request.get_full_path())
return clist

def title(self, obj):
return '%s RSS Feed' % obj.long_name()

def subtitle(self):
if self.significant:
subtitle = 'Significant document changes'
else:
subtitle = 'Document changes'
return subtitle

def link(self):
return self.host

def feed_url(self, obj):
return self.feed_url

def feed_guid(self, obj):
feed_id = uuid.uuid5(uuid.NAMESPACE_URL, str(self.feed_url))
return feed_id.urn

def items(self, obj):
from ietf.community.utils import docs_tracked_by_community_list
documents = docs_tracked_by_community_list(obj).values_list('pk', flat=True)
since = timezone.now() - datetime.timedelta(days=21)
events = DocEvent.objects.filter(
doc__id__in=documents,
time__gte=since,
).distinct().order_by('-time', '-id').select_related("doc")
if self.significant:
events = events.filter(type="changed_state", statedocevent__state__in=list(states_of_significant_change()))
return events[:50]

def item_title(self, item):
title = item.doc.title
if item.type == 'sent_last_call':
title = "Last Call Issued: %s" % title
return title

def item_description(self, item):
return item.desc # {{ entry.desc|linebreaksbr|force_escape }}

def item_link(self, item):
return item.doc.get_absolute_url()

def item_guid(self, item):
return "urn:uid:%s" % item.id

def item_pubdate(self, item):
return item.time

def item_updateddate(self, item):
return item.time

def item_author_name(self, item):
return str(item.by)

def item_extra_kwargs(self, item):
extra = super(CommunityFeed, self).item_extra_kwargs(item)
extra.update({"ietf_type": item.type})
if item.doc.stream.slug:
extra.update({"ietf_stream": item.doc.stream.slug})
extra.update({"ietf_group": item.doc.group.acronym})
if item.doc.shepherd:
extra.update({"ietf_shepherd": item.doc.shepherd.person.name})
if item.doc.ad:
extra.update({"ietf_ad": item.doc.ad.name})
if item.doc.states:
extra.update({"ietf_state": [{"type": str(state.type), "value": state.slug} for state in item.doc.states.all()]})
if item.doc.tags:
extra.update({"ietf_tag": [tag.slug for tag in item.doc.tags.all()]})
if item.type == "new_revision":
if item.doc.abstract:
extra.update({"ietf_abstract": item.doc.abstract})
if item.doc.rev:
extra.update({"ietf_version": item.doc.rev})
return extra
43 changes: 5 additions & 38 deletions ietf/community/views.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
# Copyright The IETF Trust 2012-2023, All Rights Reserved
# Copyright The IETF Trust 2012-2024, All Rights Reserved
# -*- coding: utf-8 -*-


import csv
import datetime
import json
import uuid

from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import get_object_or_404, render
from django.contrib.auth.decorators import login_required
from django.utils import timezone
from django.utils.html import strip_tags

import debug # pyflakes:ignore
Expand All @@ -19,9 +16,9 @@
from ietf.community.forms import SearchRuleTypeForm, SearchRuleForm, AddDocumentsForm, SubscriptionForm
from ietf.community.utils import can_manage_community_list
from ietf.community.utils import docs_tracked_by_community_list, docs_matching_community_list_rule
from ietf.community.utils import states_of_significant_change, reset_name_contains_index_for_rule
from ietf.community.utils import reset_name_contains_index_for_rule
from ietf.group.models import Group
from ietf.doc.models import DocEvent, Document
from ietf.doc.models import Document
from ietf.doc.utils_search import prepare_document_table
from ietf.person.utils import lookup_persons
from ietf.utils.decorators import ignore_view_kwargs
Expand Down Expand Up @@ -244,38 +241,8 @@ def export_to_csv(request, email_or_name=None, acronym=None):

@ignore_view_kwargs("group_type")
def feed(request, email_or_name=None, acronym=None):
clist = lookup_community_list(request, email_or_name, acronym) # may raise Http404
significant = request.GET.get('significant', '') == '1'

documents = docs_tracked_by_community_list(clist).values_list('pk', flat=True)
since = timezone.now() - datetime.timedelta(days=14)

events = DocEvent.objects.filter(
doc__id__in=documents,
time__gte=since,
).distinct().order_by('-time', '-id').select_related("doc")

if significant:
events = events.filter(type="changed_state", statedocevent__state__in=list(states_of_significant_change()))

host = request.get_host()
feed_url = 'https://%s%s' % (host, request.get_full_path())
feed_id = uuid.uuid5(uuid.NAMESPACE_URL, str(feed_url))
title = '%s RSS Feed' % clist.long_name()
if significant:
subtitle = 'Significant document changes'
else:
subtitle = 'Document changes'

return render(request, 'community/atom.xml', {
'clist': clist,
'entries': events[:50],
'title': title,
'subtitle': subtitle,
'id': feed_id.urn,
'updated': timezone.now(),
}, content_type='text/xml')

from .feeds import CommunityFeed
return CommunityFeed()(request, email_or_name=email_or_name, acronym=acronym)

@login_required
@ignore_view_kwargs("group_type")
Expand Down
52 changes: 0 additions & 52 deletions ietf/templates/community/atom.xml

This file was deleted.

Loading