Torque/RSSTicker

From TDN

Contents

Simple RSS Ticker

The RSS Ticker is a simple RSS feed parser and displayer, which allows a basic level of integration of remote RSS resources in a Torque application. This is useful for news, update notification, and so forth. It is new in Torque 1.4.

It is contained in tutorial.base, specifically, in tutorial.base/client/ui/mainMenuGui.gui. There is a GuiMLTextCtrl called RSSFeedMLText, and then some code starting after the OBJECT WRITE END marker.

When the MainMenuGui is awakened, it schedules kickOffRSS() to be called in 50ms; this creates a new TCPObject which downloads the specified RSS feed, and when it's downloaded, parses it and puts the results in the ML control.

Typically, the feed is provided by Feedburner.com, as you can see the GarageGames feeds here

Note: If you have any trouble with the script, there is also an example in the latest Torque's tutorial.base mod.

Configuring the RSS Ticker

The important configuration operations are all located in a block of global variables.

// RSS ticker configuration:
$RSSFeed::serverName = "www.garagegames.com";
$RSSFeed::serverPort = 80;
$RSSFeed::serverURL  = "/rss.php?feed=blog&id=8863";
$RSSFeed::userAgent = "Torque/1.4";

The parameters specify in order, the server, port, and URL to grab content from. The user agent is provided mostly for completeness (and in case we encounter a particular anal set of filtering rules).

The Full script

function RSSFeedObject::onConnected(%this)
{
	echo("RSS Feed");
	echo("   - Requesting RSS data at URL: " @ $RSSFeed::serverURL );

	// Reset some useful state information.
	$RSSFeed::lineCount = 0;
	$RSSFeed::requestResults = "";
	
	// Request our RSS.
	%this.send("GET " @ $RSSFeed::serverURL @ " HTTP/1.0\nHost: " @ $RSSFeed::serverName @ "\nUser-Agent: " @ $RSSFeed::userAgent @ "\n\r\n\r\n");
}

function RSSFeedObject::onLine(%this, %line)
{
	// Collate info.
	$RSSFeed::lineCount++;
	$RSSFeed::requestResults = $RSSFeed::requestResults @ %line;
}

function RSSFeedObject::getTagContents(%this, %string, %tag, %startChar)
{
 // This function occasionally makes Torque hard crash. It doesn't
 // seem to do it anymore but be careful!
 
	// Ok, get thing between <%tag> and </%tag> after char #
	// %startChar in the passed string.
	
	%startTag = "<" @ %tag @ ">";
	%endTag   = "</" @ %tag @ ">";
	
	%startTagOffset = strpos(%string, %startTag, %startChar);
	
	// Compensate for presence of start tag.
	%startOffset = %startTagOffset + strlen(%startTag);
	
	// Ok, now look for end tag.
	%endTagOffset = strpos(%string, %endTag, %startOffset - 1);

 	// If we didn't find it, bail. 
	if(%endTagOffset < 0)
    		return "";
    
 	// Evil hack - store last found item in a global.
	 %this.lastOffset = %endTagOffset;
		
	// And get & return the substring between the tags.
	%result = getSubStr(%string, %startOffset, %endTagOffset - %startOffset);
	
	// Do a little mojo to deal with " and some other htmlentities.
	%result = strreplace(%result, "&quot;", "\"");
	%result = strreplace(%result, "&amp;",  "&");
	
	return %result;
}

function RSSFeedObject::onDisconnect(%this)
{
	// Ok, we have a full buffer now, hopefully. Let's process it.
	echo("   - Got " @ $RSSFeed::lineCount @ " lines.");
	
	// We want the feed title and the first three headlines + links.
	
	// Feed title - get the first <title> occurence in the string.
	%title = %this.getTagContents($RSSFeed::requestResults, "title", 0);
	%titleLink = %this.getTagContents($RSSFeed::requestResults, "link", 0);
	
	echo("   - Feed title: '" @ %title @ "'");
	echo("   - Feed link:  '" @ %titleLink @ "'");
	
	// Ok, get the first three headlines, if any...
	for(%i = 0; %i<3; %i++)
	{
	   %headline[%i]     = %this.getTagContents($RSSFeed::requestResults, "title", %this.lastOffset);
	   %headlineLink[%i] = %this.getTagContents($RSSFeed::requestResults, "link", %this.lastOffset);
	   
	   // Skip the content - it's not going to do anything but confuse us.
	   %garbage          = %this.getTagContents($RSSFeed::requestResults, "content:encoded", %this.lastOffset);

    //  And debug spam...
    echo("   - Headline      #" @ %i @ " : '" @ %headline[%i] @ "'");
    echo("   - Headline Link #" @ %i @ " : '" @ %headlineLink[%i] @ "'");
	}

  // Generate contents for our ML control.
  RSSFeedMLText.setText("<lmargin%:2><font:Arial Bold:20>" @ %title @ "<font:Arial:14>\n");
  for(%i=0; %i<3; %i++)
     RSSFeedMLText.addText("<a:" @ getSubstr(%headlineLink[%i], 7, 1000) @ ">" @ %headline[%i] @ "</a>\n", false);
  RSSFeedMLText.addText("<just:right><a:" @ getSubstr(%titleLink, 7, 1000) @ ">" @ "[ Read more... ]" @ "</a>", true);
	
}

function kickOffRSS()
{
   new TCPObject(RSSFeedObject);
   RSSFeedObject.connect($RSSFeed::serverName @ ":" @ $RSSFeed::serverPort);
}

function MainMenuGui::onWake(%this)
{
   // Kick off an update on next tick.
   if(!$pref::RSS::disableFeedCheck)
      schedule(50, 0, kickOffRSS);
}

The Full script with content - SphyxGames

function RSSFeedObject::onConnected(%this)
{
	echo("RSS Feed");
	echo("   - Requesting RSS data at URL: " @ $RSSFeed::serverURL );

	// Reset some useful state information.
	$RSSFeed::lineCount = 0;
	$RSSFeed::requestResults = "";
	
	// Request our RSS.
	%this.send("GET " @ $RSSFeed::serverURL @ " HTTP/1.0\nHost: " @ $RSSFeed::serverName @ "\nUser-Agent: " @ $RSSFeed::userAgent @ "\n\r\n\r\n");
}

function RSSFeedObject::onLine(%this, %line)
{
	// Collate info.
	$RSSFeed::lineCount++;
	$RSSFeed::requestResults = $RSSFeed::requestResults @ %line;
}

function RSSFeedObject::getTagContents(%this, %string, %tag, %startChar)
{
 // This function occasionally makes Torque hard crash. It doesn't
 // seem to do it anymore but be careful!
 
	// Ok, get thing between <%tag> and </%tag> after char #
	// %startChar in the passed string.
	
	%startTag = "<" @ %tag @ ">";
	%endTag   = "</" @ %tag @ ">";
	
	%startTagOffset = strpos(%string, %startTag, %startChar);
	
	// Compensate for presence of start tag.
	%startOffset = %startTagOffset + strlen(%startTag);
	
	// Ok, now look for end tag.
	%endTagOffset = strpos(%string, %endTag, %startOffset - 1);

 	// If we didn't find it, bail. 
	if(%endTagOffset < 0)
    		return "";
    
 	// Evil hack - store last found item in a global.
	 %this.lastOffset = %endTagOffset;
		
	// And get & return the substring between the tags.
	%result = getSubStr(%string, %startOffset, %endTagOffset - %startOffset);
	
	// Do a little mojo to deal with " and some other htmlentities.
	%result = strreplace(%result, "&quot;", "\"");
	%result = strreplace(%result, "&amp;",  "&");
	
	return %result;
}

function RSSFeedObject::onDisconnect(%this)
{
	// Ok, we have a full buffer now, hopefully. Let's process it.
	echo("   - Got " @ $RSSFeed::lineCount @ " lines.");
	
	// We want the feed title and the first three headlines + links.
	
	// Feed title - get the first <title> occurence in the string.
	%title = %this.getTagContents($RSSFeed::requestResults, "title", 0);
	%desc = %this.getTagContents($RSSFeed::requestResults, "description", 0);
	
	echo("   - Feed title: '" @ %title @ "'");
	
	// Ok, get the first three headlines, if any...
	for(%i = 0; %i<3; %i++)
	{
		%headline[%i]     = %this.getTagContents($RSSFeed::requestResults, "title", %this.lastOffset);
		%desc[%i]         = %this.getTagContents($RSSFeed::requestResults, "description", %this.lastOffset);
		echo("   - Headline      #" @ %i @ " : '" @ %headline[%i] @ "'");
		echo("   - Description   #" @ %i @ " : '" @ %desc[%i] @ "'");
	}
  // Generate contents for our ML control.
  RSSFeedMLText.setText("<lmargin%:2><font:Arial Bold:20>" @ %title @ "<font:Arial:14>\n \n");
  for(%i=0; %i<3; %i++)
  RSSFeedMLText.addText(%headline[%i] @ "\n" @ %desc[%i] @ "\n \n", false);
}

function kickOffRSS()
{
   new TCPObject(RSSFeedObject);
   RSSFeedObject.connect($RSSFeed::serverName @ ":" @ $RSSFeed::serverPort);
}

function MainMenuGui::onWake(%this)
{
   // Kick off an update on next tick.
   if(!$pref::RSS::disableFeedCheck)
      schedule(50, 0, kickOffRSS);
}