diff --git a/tildes/tildes/routes.py b/tildes/tildes/routes.py
index e0a197c..bd8b8f4 100644
--- a/tildes/tildes/routes.py
+++ b/tildes/tildes/routes.py
@@ -19,6 +19,8 @@ from tildes.resources.user import user_by_username
def includeme(config: Configurator) -> None:
"""Set up application routes."""
config.add_route("home", "/")
+ config.add_route("home_atom", "/topics.atom")
+ config.add_route("home_rss", "/topics.rss")
config.add_route("search", "/search")
@@ -37,6 +39,8 @@ def includeme(config: Configurator) -> None:
config.add_route("new_topic", "/new_topic", factory=group_by_path)
config.add_route("group_topics", "/topics", factory=group_by_path)
+ config.add_route("group_topics_atom", "/topics.atom", factory=group_by_path)
+ config.add_route("group_topics_rss", "/topics.rss", factory=group_by_path)
config.add_route("group_search", "/search", factory=group_by_path)
diff --git a/tildes/tildes/templates/base.atom.jinja2 b/tildes/tildes/templates/base.atom.jinja2
new file mode 100644
index 0000000..f238459
--- /dev/null
+++ b/tildes/tildes/templates/base.atom.jinja2
@@ -0,0 +1,14 @@
+{# Copyright (c) 2021 Tildes contributors #}
+{# SPDX-License-Identifier: AGPL-3.0-or-later #}
+
+
+
#}
+{# SPDX-License-Identifier: AGPL-3.0-or-later #}
+
+
+
#}
+{# SPDX-License-Identifier: AGPL-3.0-or-later #}
+
+{% extends 'topic_listing.atom.jinja2' %}
+
+{% block feed_title %}Tildes Atom feed{% endblock %}
diff --git a/tildes/tildes/templates/home.rss.jinja2 b/tildes/tildes/templates/home.rss.jinja2
new file mode 100644
index 0000000..a353007
--- /dev/null
+++ b/tildes/tildes/templates/home.rss.jinja2
@@ -0,0 +1,8 @@
+{# Copyright (c) 2021 Tildes contributors
#}
+{# SPDX-License-Identifier: AGPL-3.0-or-later #}
+
+{% extends 'topic_listing.rss.jinja2' %}
+
+{% block channel_title %}Tildes{% endblock %}
+{% block channel_link %}https://tildes.net/{% endblock %}
+{% block channel_description %}Topics RSS feed{% endblock %}
diff --git a/tildes/tildes/templates/topic_listing.atom.jinja2 b/tildes/tildes/templates/topic_listing.atom.jinja2
new file mode 100644
index 0000000..06f5150
--- /dev/null
+++ b/tildes/tildes/templates/topic_listing.atom.jinja2
@@ -0,0 +1,39 @@
+{# Copyright (c) 2021 Tildes contributors
#}
+{# SPDX-License-Identifier: AGPL-3.0-or-later #}
+
+{% extends 'base.atom.jinja2' %}
+
+{% block feed_title %}~{{ group.path }} - Tildes{% endblock %}
+
+{% block feed_entries %}
+
+ {% for topic in topics %}
+
Comments URL: https://tildes.net{{ topic.permalink }}
+Votes: {{ topic.num_votes }}
+Comments: {{ topic.num_comments }}
+ ]]> + #}
+{# SPDX-License-Identifier: AGPL-3.0-or-later #}
+
+{% extends 'base.rss.jinja2' %}
+
+{% block channel_title %}~{{ group.path }} - Tildes{% endblock %}
+{% block channel_link %}https://tildes.net/~{{ group.path }}{% endblock %}
+{% block channel_description %}Topics in ~{{ group.path }}{% endblock %}
+
+{% block channel_items %}
+
+ {% for topic in topics %}
+ -
+
+ {% if topic.is_link_type %}
+ {{ topic.link }}
+ {% else %}
+ {{ topic.permalink }}
+ {% endif %}
+ Link URL: {{ topic.link }}
+ {% elif topic.is_text_type %}
+ {{ topic.rendered_html|safe }}
+
+ {% endif %}
+ Comments URL: https://tildes.net{{ topic.permalink }}
+ Votes: {{ topic.num_votes }}
+ Comments: {{ topic.num_comments }}
+ ]]>
+ {{ topic.user.username }}
+ {{ topic.permalink }}
+ {{ topic.created_time.strftime("%a, %d %b %Y %T %z") }}
+
+ {% endfor %}
+
+{% endblock %}
diff --git a/tildes/tildes/views/topic.py b/tildes/tildes/views/topic.py
index faef389..675144e 100644
--- a/tildes/tildes/views/topic.py
+++ b/tildes/tildes/views/topic.py
@@ -142,7 +142,11 @@ def post_group_topics(
@view_config(route_name="home", renderer="home.jinja2")
+@view_config(route_name="home_atom", renderer="home.atom.jinja2")
+@view_config(route_name="home_rss", renderer="home.rss.jinja2")
@view_config(route_name="group", renderer="topic_listing.jinja2")
+@view_config(route_name="group_topics_atom", renderer="topic_listing.atom.jinja2")
+@view_config(route_name="group_topics_rss", renderer="topic_listing.rss.jinja2")
@use_kwargs(TopicListingSchema())
def get_group_topics( # noqa
request: Request,
@@ -159,7 +163,9 @@ def get_group_topics( # noqa
# period needs special treatment so we can distinguish between missing and None
period = kwargs.get("period", missing)
- is_home_page = request.matched_route.name == "home"
+ is_home_page = request.matched_route.name in ["home", "home_atom", "home_rss"]
+ is_atom = request.matched_route.name in ["home_atom", "group_topics_atom"]
+ is_rss = request.matched_route.name in ["home_rss", "group_topics_rss"]
if is_home_page:
# on the home page, include topics from the user's subscribed groups
@@ -192,6 +198,11 @@ def get_group_topics( # noqa
if period is missing:
period = default_settings.period
+ # force Newest sort order, and All Time period, for RSS feeds
+ if is_atom or is_rss:
+ order = TopicSortOption.NEW
+ period = None
+
# set up the basic query for topics
query = (
request.query(Topic)
@@ -285,6 +296,11 @@ def get_group_topics( # noqa
else:
financial_data = None
+ if is_atom:
+ request.response.content_type = "application/atom+xml"
+ if is_rss:
+ request.response.content_type = "application/rss+xml"
+
return {
"group": request.context,
"groups": groups,