Add RSS and JSON feeds of incidents and an open dataset
All checks were successful
Build and Deploy to Production / test (push) Successful in 21s
Build and Deploy to Production / build (push) Successful in 49s
Build and Deploy to Production / deploy (push) Successful in 37s

Let readers and bots follow new incidents without polling the card:
/:locale/feed.xml (RSS 2.0) and /:locale/feed.json (JSON Feed 1.1),
the latest 50 incidents with stable IDs, advertised in the page head
and footer.

/data.json publishes every datacenter with its specs and sourced
incidents under CC BY 4.0, for journalists and OSINT reuse.

Assisted-by: Claude:opus-5
This commit is contained in:
Sergei Poljanski 2026-10-12 05:31:26 +04:00
commit 03355983b4
Signed by: asxpi
GPG key ID: 4F8851660FA4121B
8 changed files with 215 additions and 0 deletions

View file

@ -2,5 +2,6 @@
<p><%= t(:footer) %></p>
<p class="credits"><%= t(:credits_ai) %>
<%== format(Rack::Utils.escape_html(t(:credits_hym)), link: '<a href="https://hackyourmom.com/en/karta-data-czentriv-na-rasii/" target="_blank" rel="noopener">hackyourmom</a>') %></p>
<p><a href="/<%= @locale %>/feed.xml">RSS</a> · <a href="/<%= @locale %>/feed.json">JSON Feed</a> · <a href="/data.json"><%= t(:open_data) %></a></p>
<p>© <%= Date.today.year %> <a href="https://asxp.io">asxp.io</a> · <a href="<%= BingoWeb::SOURCE_URL %>" rel="noopener"><%= t(:source_code) %></a></p>
</footer>

24
views/feed_rss.erb Normal file
View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<% base = base_url %>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title><%= format(t(:feed_title), site: t(:title)) %></title>
<link><%= base %>/<%= @locale %></link>
<description><%= t(:tagline) %></description>
<language><%= @locale %></language>
<atom:link href="<%= base %>/<%= @locale %>/feed.xml" rel="self" type="application/rss+xml"/>
<% if (top = @incidents.first) %>
<lastBuildDate><%= [*@incidents.map(&:updated_at).compact, feed_time(top)].max.utc.rfc2822 %></lastBuildDate>
<% end %>
<% @incidents.each do |i| %>
<item>
<title><%= incident_headline(i) %></title>
<link><%= base %><%= dc_path(i.datacenter) %></link>
<guid isPermaLink="false"><%= incident_id(i) %></guid>
<pubDate><%= feed_time(i).rfc2822 %></pubDate>
<category><%= kind_label(i.kind) %></category>
<description><%= incident_html(i) %></description>
</item>
<% end %>
</channel>
</rss>

View file

@ -17,6 +17,8 @@
<link rel="alternate" hreflang="x-default" href="<%= base %><%= @x_default %>">
<% end %>
<link rel="sitemap" type="application/xml" href="/sitemap.xml">
<link rel="alternate" type="application/rss+xml" title="<%= format(t(:feed_title), site: t(:title)) %>" href="<%= base %>/<%= @locale %>/feed.xml">
<link rel="alternate" type="application/feed+json" title="<%= format(t(:feed_title), site: t(:title)) %>" href="<%= base %>/<%= @locale %>/feed.json">
<meta property="og:type" content="website">
<meta property="og:site_name" content="<%= t(:title) %>">
<meta property="og:title" content="<%= @title %>">