Forum Discussion

cjdinger's avatar
cjdinger
Leader
4 years ago

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('&','&amp;')}" 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('&','&amp;')}" 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('&','&amp;')}" 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!

  • Love this, cjdinger and if you don't mind, we're going to borrow this to use in our own community. We've been looking for a good way to automate our events from the community into a Google Calendar and this fits the bill!

  • It's why I shared it Natkinson ! And if you find some magic changes that make this better for a GCal feed, please let me know. It's not something I looked into.

    Was thinking I could expand to at least include a link in each item to the ICS download...but I have not looked at what that would take.

    • Natkinson's avatar
      Natkinson
      Genius

      Well we appreciate the share! I'll play around with it, but for now we're just going to use the magic of Zapier to grab this RSS feed and toss all the info into a calendar event