| 1228 | |
| 1229 | @requires(str, "uri") |
| 1230 | def feed(self, environ, request, uri): |
| 1231 | conf = self.isso.conf.section("rss") |
| 1232 | if not conf.get("base"): |
| 1233 | raise NotFound |
| 1234 | |
| 1235 | args = {"uri": uri, "order_by": "id", "asc": 0, "limit": conf.getint("limit")} |
| 1236 | try: |
| 1237 | args["limit"] = max(int(request.args.get("limit")), args["limit"]) |
| 1238 | except TypeError: |
| 1239 | pass |
| 1240 | except ValueError: |
| 1241 | return BadRequest("limit should be integer") |
| 1242 | comments = self.comments.fetch(**args) |
| 1243 | base = conf.get("base").rstrip("/") |
| 1244 | hostname = urlparse(base).netloc |
| 1245 | |
| 1246 | # Let's build an Atom feed. |
| 1247 | # RFC 4287: https://tools.ietf.org/html/rfc4287 |
| 1248 | # RFC 4685: https://tools.ietf.org/html/rfc4685 (threading extensions) |
| 1249 | # For IDs: http://web.archive.org/web/20110514113830/http://diveintomark.org/archives/2004/05/28/howto-atom-id |
| 1250 | feed = ET.Element( |
| 1251 | "feed", {"xmlns": "http://www.w3.org/2005/Atom", "xmlns:thr": "http://purl.org/syndication/thread/1.0"} |
| 1252 | ) |
| 1253 | |
| 1254 | # For feed ID, we would use thread ID, but we may not have |
| 1255 | # one. Therefore, we use the URI. We don't have a year |
| 1256 | # either... |
| 1257 | id = ET.SubElement(feed, "id") |
| 1258 | id.text = "tag:{hostname},2018:/isso/thread{uri}".format(hostname=hostname, uri=uri) |
| 1259 | |
| 1260 | # For title, we don't have much either. Be pretty generic. |
| 1261 | title = ET.SubElement(feed, "title") |
| 1262 | title.text = "Comments for {hostname}{uri}".format(hostname=hostname, uri=uri) |
| 1263 | |
| 1264 | comment0 = None |
| 1265 | |
| 1266 | for comment in comments: |
| 1267 | if comment0 is None: |
| 1268 | comment0 = comment |
| 1269 | |
| 1270 | entry = ET.SubElement(feed, "entry") |
| 1271 | # We don't use a real date in ID either to help with |
| 1272 | # threading. |
| 1273 | id = ET.SubElement(entry, "id") |
| 1274 | id.text = "tag:{hostname},2018:/isso/{tid}/{id}".format(hostname=hostname, tid=comment["tid"], id=comment["id"]) |
| 1275 | title = ET.SubElement(entry, "title") |
| 1276 | title.text = "Comment #{}".format(comment["id"]) |
| 1277 | updated = ET.SubElement(entry, "updated") |
| 1278 | updated.text = "{}Z".format(datetime.fromtimestamp(comment["modified"] or comment["created"]).isoformat()) |
| 1279 | author = ET.SubElement(entry, "author") |
| 1280 | name = ET.SubElement(author, "name") |
| 1281 | name.text = comment["author"] |
| 1282 | ET.SubElement(entry, "link", {"href": "{base}{uri}#isso-{id}".format(base=base, uri=uri, id=comment["id"])}) |
| 1283 | content = ET.SubElement( |
| 1284 | entry, |
| 1285 | "content", |
| 1286 | { |
| 1287 | "type": "html", |