Events (occasion) RSS feed for syndication
We're using the Events module more, but one thing we were missing was a way to syndicate the events to other sites in a useful way: chronological by date of upcoming event, including title, desc, feature image...etc.
I created an endpoint component to produce the RSS feed that I think we need for this. I've decided to share it here in case others find it useful. A few values are coded for our community but most are easily replaced for your case. In the comments I included some sample URLs that control which labels are included in the feed, how many items ahead, etc.
If you'd like to see an example of this output, here's a sample feed from our community.
<?xml version="1.0" encoding="UTF-8"?>
<#-- sample URLs:
Default event board:
https://communities.sas.com/plugins/custom/sasinstitute/sasinstitute/events-rss
Specific event board:
https://communities.sas.com/plugins/custom/sasinstitute/sasinstitute/events-rss?board=community-events
Specific event board, no event message body in feed:
https://communities.sas.com/plugins/custom/sasinstitute/sasinstitute/events-rss?board=community-events&description=false
Next 10 events:
https://communities.sas.com/plugins/custom/sasinstitute/sasinstitute/events-rss?board=community-events&size=10
Next 5 events for "Users Groups":
https://communities.sas.com/plugins/custom/sasinstitute/sasinstitute/events-rss?board=community-events&label=Users%20Groups
-->
<#-- our community domain, checking for stage vs prod -->
<#assign root="https://communities.sas.com"/>
<#if config.getString("phase", "prod") == "stage">
<#assign root = "https://communities-lithiumstage.sas.com" />
</#if>
<#assign board = http.request.parameters.name.get("board","events")/>
<#assign label = http.request.parameters.name.get("label", "")/>
<#assign filter = http.request.parameters.name.get("filter","upcoming")/>
<#assign include_desc = http.request.parameters.name.get("description", "true")/>
<#assign size= http.request.parameters.name.get("size","5")/>
<#assign time_filter = ""/>
<#if filter != "">
<#assign time_filter = "AND occasion_data.status = '${filter}'"/>
</#if>
<#assign label_filter = ""/>
<#if (label)?has_content>
<#assign label_filter = "AND labels.text MATCHES('${label}')"/>
</#if>
<#assign board_href = "#"/>
<#assign board_title = "Events"/>
<#assign board_description = ""/>
<#assign boardq = rest("2.0", "/search?q=" + "select title, description, view_href from boards where id='${board}' and conversation_style='occasion'"?url)/>
<#if boardq.data?? && boardq.data.items?? && boardq.data.items?size gt 0>
<#assign board_href = "${boardq.data.items[0].view_href}"/>
<#assign board_title = "${boardq.data.items[0].title}"/>
<#assign board_description = "${boardq.data.items[0].description}"/>
<#if board_description==""><#assign board_description = "${board_title}"/></#if>
</#if>
<#assign events = rest("2.0", "/search?q=" +
"select subject, view_href, body, videos, images, occasion_data.start_time, labels from messages where board.id='${board}' ${time_filter} ${label_filter} AND depth=0 order by occasion_data.start_time ASC LIMIT ${size}"?url
)/>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel>
<title>${board_title}</title>
<link>${root}${board_href}</link>
<atom:link href="${http.request.url?replace('&','&')}" rel="self" type="application/rss+xml"/>
<description>${board_description}</description>
<#if events.data?? && events.data.items??>
<#list events.data.items as event >
<item>
<title>${event.subject} | ${event.occasion_data.start_time?datetime?string("dd-MMM-yyyy")}</title>
<link>${root}${event.view_href}</link>
<guid>${root}${event.view_href}</guid>
<#if include_desc == "true">
<description>${event.body?html}</description>
</#if>
<#-- add either an image from the message or a video thumb, whichever we have -->
<#if event.images?? && event.images.query??>
<#assign images = rest("2.0", "/search?q=" + "${event.images.query}"?url )/>
<#list images.data.items as image>
<#-- need to escape & in the XML, and these URLs can sometimes have them -->
<enclosure url="${root}${image.medium_href?replace('&','&')}" length="0" type="image/jpeg"/>
<#break>
</#list>
<#elseif event.videos?? && event.videos.query??>
<#assign videos = rest("2.0", "/search?q=" + "${event.videos.query}"?url )/>
<#list videos.data.items as video>
<enclosure url="${video.thumb_href?replace('&','&')}" length="0" type="application/x-shockwave-flash"/>
<dc:type>MovingImage</dc:type>
<#break>
</#list>
</#if>
<#if event.labels?? && event.labels.query??>
<#assign labels = rest("2.0", "/search?q=" + "${event.labels.query}"?url )/>
<#list labels.data.items as label>
<#-- category tag: good enough for WordPress, so good enough for us -->
<category><![CDATA[${label.text?html}]]></category>
</#list>
</#if>
<#-- this "pubDate" will always be in the future which may confuse some aggregators -->
<#-- but I didn't know how else to encode the event date/time in the feed -->
<pubDate>${event.occasion_data.start_time?datetime?string["EEE, dd MMM yyyy HH:mm:ss"]} GMT</pubDate>
</item>
</#list>
</#if>
</channel>
</rss>
I've tried the feed in some aggregators like Feedly and in Microsoft Outlook -- it seems to pass muster. Questions and suggestions are welcome!