feat: add JSON feed support for weather art

- Implement JSON feed generation in the RssController
- Add new API endpoint to serve JSON feed
- Update RSS feed view to include hidden machine-readable data

This commit introduces a new feature that allows the application to
serve weather art data in JSON format. The JSON feed includes
metadata such as the title, description, and additional custom
fields for better integration with other services. The changes
also enhance the existing RSS feed by embedding machine-readable
data within the HTML structure, improving accessibility and
usability for automated systems.
This commit is contained in:
songtianlun 2025-03-05 14:59:02 +08:00
parent e22d3d86de
commit 4e322bd6e9
2 changed files with 59 additions and 1 deletions

View File

@ -4,6 +4,37 @@ class RssController < ApplicationController
respond_to do |format|
format.rss { render layout: false }
format.json { render json: generate_json_feed }
end
end
private
def generate_json_feed
{
version: "https://jsonfeed.org/version/1.1",
title: "Today AI Weather Art",
home_page_url: root_url,
feed_url: rss_feed_url(format: :json),
items: @weather_arts.map do |art|
{
id: city_weather_art_url(art.city, art),
url: city_weather_art_url(art.city, art),
title: "#{art.city.full_name} Weather Art",
content_html: "<p>#{art.description}</p>",
date_published: art.created_at.iso8601,
image: art.image.attached? ? rails_blob_url(art.webp_image.processed) : nil,
# 自定义字段
_weather: {
country: art.city&.country&.name,
city: art.city&.name,
state: art.city&.state&.name,
description: art.description,
prompt: art.prompt,
date: art.weather_date&.strftime("%Y-%m-%d")
}
}
end
}
end
end

View File

@ -13,7 +13,34 @@ xml.rss version: "2.0",
@weather_arts.each do |art|
xml.item do
xml.title "#{art.city.full_name} Weather Art"
xml.description "Weather art for #{art.city.full_name} on #{art.weather_date&.strftime('%Y-%m-%d')}"
# xml.description "Weather art for #{art.city.full_name} on #{art.weather_date&.strftime('%Y-%m-%d')}"
xml.description do
content = <<~HTML
<div class="weather-art-data">
<p>Weather art for #{art.city.full_name} on #{art.weather_date&.strftime('%Y-%m-%d')}</p>
#{' '}
<!-- 添加隐藏的机器可读数据但使用data属性 -->
<div style="display:none"#{' '}
data-country="#{CGI.escapeHTML(art.city&.country&.name.to_s)}"
data-state="#{CGI.escapeHTML(art.city&.state&.name.to_s)}"
data-city="#{CGI.escapeHTML(art.city&.name.to_s)}"
data-weather-date="#{art.weather_date&.strftime('%Y-%m-%d')}"
data-description="#{CGI.escapeHTML(art.description.to_s)}"
data-prompt="#{CGI.escapeHTML(art.prompt.to_s)}">
</div>
#{' '}
<!-- 或使用Meta标签形式 -->
<meta name="weather:country" content="#{CGI.escapeHTML(art.city&.country&.name.to_s)}">
<meta name="weather:state" content="#{CGI.escapeHTML(art.city&.state&.name.to_s)}">
<meta name="weather:city" content="#{CGI.escapeHTML(art.city&.name.to_s)}">
<meta name="weather:date" content="#{art.weather_date&.strftime('%Y-%m-%d')}">
<meta name="weather:description" content="#{CGI.escapeHTML(art.description.to_s)}">
<meta name="weather:prompt" content="#{CGI.escapeHTML(art.prompt.to_s)}">
</div>
HTML
xml.cdata!(content)
end
xml.pubDate art.created_at.to_fs(:rfc822)
xml.link city_weather_art_url(art.city, art)
xml.guid city_weather_art_url(art.city, art)