on myRssWriter (f, title, link, description, language="none", flCategories=false, maxdays=infinity, adrcallback=nil, adrblog=radio.weblog.init (), adrGetUrlCallback=nil) { «Changes «5/8/02; 8:08:46 PM by DW «Encode category names. «5/8/02; 9:34:43 AM by DW «Allow the user to completely replace writeRssFile. We check user.radio.callbacks.writeRssFile. If the table is non-empty, we loop over the table calling procedures, passing the parameter list we received. The first one that doesn't scripterror gets to speak for us. This allows people to experiment with different formats and encoding, and see how those changes interact with aggregators, incl the one that's built into Radio. We can't afford to experiment with our entire installed base. So this makes it possible for developers to experiment, learn, and perhaps will allow the format(s) we support to evolve. «4/22/02; 2:39:15 PM by DW «Entity-encode the link sub-element of item. «4/11/02; 9:19:00 AM by DW «Add support for description filter callbacks. «4/7/02; 9:55:21 AM by DW «Do the macro processing or descriptions unconditionally, and in-line instead of calling radio.string.processMacros, which was only processing the descriptions if it contained "<%". This broke shortcuts. Prior art is the Manila-Blogger Bridge Tool, which unconditionally processes macros. «3/12/02; 2:50:23 PM by JES «If the pref is set, auto-generate elements for each item. The url for the is determined by calling a callback, whose address is specified in the new optional adrGetUrlCallback parameter. «The callback itself takes two parameters: adrpost -- the address of the post, and adrurl -- the address of a string in which to save the url. If the callback returns true, then the element is added. «3/11/02; 2:55:28 PM by DW «If Titles-And-Links are turned off, don't include them in the RSS output. «3/11/02; 7:45:56 AM by DW «For each post, if it has elements called link and title, add those to the RSS output. «1/20/02; 9:47:31 AM by DW «Factored from radio.weblog.publishRss. «A single bottleneck for generating RSS. «We get the file as a key to managing the cache, so let's also write the file. «The callback, if supplied, determines if a post is to be included in the RSS file. If not present, the posts in the loop are included. «1/20/02; 9:07:41 AM by DW «Process macros as RSS is being generated. «Optimized using cache at system.temp.radio.rssCache. Average time to generate RSS for Dave's Handsome Radio Blog went from 40 ticks to 5 ticks. Moral of the story, encoding text takes a lot of cycles. «1/20/02; 8:16:28 AM by DW «Respect the preference settings for managing editor and webmaster when generating the main RSS feed. «12/20/01; 2:09:47 AM by JES «Use file.writeTextFile instead of file.writeWholeFile to write the RSS. «12/9/01; 12:42:35 PM by DW «Get in synch with radio.weblog.publishCategoryRss, they have the same parts, similar values. «10/30/01; 2:24:35 PM by JES «Respect the pref for the max number of items to post, at adrblog^.prefs.maxOutputItemsPerChannel. «10/6/01; 9:37:10 PM by JES «Commented out code which transfers files to an FTP account. This is now accomplished through the upstreaming drivers. «3/4/01; 12:24:48 PM by PBS «Don't put a blank line at the top of RSS files. «3/1/01; 11:39:48 PM by JES «Write files out with Radu as the creator, and TEXT as the type. «2/22/01; 9:31:01 PM by JES «If this is a Mac, convert the text to Latin when building the XML. «Soft-code the year in the copyright notice; it was hard-coded for 2001. «2/17/01; 7:50:18 PM by JES «Changed the URL in the element so that it links to the HTML rendering, instead of to http://www.tbd.com/. scratchpad.myRssWriter = "called!"; local (adrcache); bundle { //set adrcache local (adrtable = @system.temp.radio.rssCache); if not defined (adrtable^) { new (tabletype, adrtable)}; adrcache = @adrtable^.[f]; if not defined (adrcache^) { new (tabletype, adrcache)}; if not defined (adrcache^.items) { new (tabletype, @adrcache^.items); }}; local (flCloud = false); bundle { //set flCloud try { if not file.exists (f) { //radio.file.getFileAttributes doesn't work if the file doesn't exist file.writeTextFile (f, " ")}; local (adrfile, adrspec); radio.file.getFileAttributes (f, @adrfile); radio.upstream.getUpstreamSpec (adrfile, @adrspec); if adrspec^.server == user.radio.prefs.rssCloud.server { if adrspec^.port == user.radio.prefs.rssCloud.port { if adrspec^.rpcPath == user.radio.prefs.rssCloud.path { flCloud = true; }}}}}; local (xmltext); bundle { //build xmltext local (indentlevel = 0); on add (s) { xmltext = xmltext + string.filledstring ("\t", indentlevel) + s + "\r\n"}; on encode (s) { if system.environment.isMac { //02/22/2001 JES: convert to Latin text return (xml.entityEncode (latinToMac.macToLatin (s), true))} else { return (xml.entityEncode (s, true))}}; add (""); add (""); «add (""); indentlevel++ add (""); indentlevel++; add (""); indentlevel++; add ("" + encode (title) + ""); add ("" + encode (link) + ""); add ("" + encode (description) + ""); if language != "none" { add ("" + language + "")}; add ("" + date.netstandardstring (clock.now ()) + ""); «local (now = clock.now()) «add ("" + html.getOneTagValue(xml.coercions.frontierValueToTaggedText(@now,0), "dateTime.iso8601") + "") «add ("http://blogs.law.harvard.edu/tech/rss") «add ("" + encode (adrblog^.prefs.webmaster) + "") «add ("" + encode (adrblog^.prefs.managingEditor) + "") add("Jon Udell, judell@mv.com");; add ("" + "Copyright " + date.year () + " " + adrblog^.prefs.authorName + ""); add("InfoWorld");; bundle { //add cloud element if flCloud { with user.radio.prefs.rssCloud { add ("")}}}; bundle { //add the items local (i, adrpost, s, ctitems = 0); local (ctdays = 0, lastday = -1, itemstext = "", lastitemdate, flinclude); for i = sizeof (adrblog^.posts) downto 1 { adrpost = @adrblog^.posts [i]; bundle { //check date rollover local (when = adrpost^.when, day, month, year, hour, minute, second); date.get (when, @day, @month, @year, @hour, @minute, @second); if lastday == -1 { //first time through loop lastday = day} else { if day != lastday { ctdays++; if ctdays == maxdays { break}; lastday = day}}}; bundle { //set flinclude flinclude = true; if adrcallback != nil { try {flinclude = adrcallback^ (adrpost)}}}; if flinclude { add (""); indentlevel++; bundle { //add title and link present in the post, if enabled if adrblog^.prefs.flTitleAndLinkOnPostForm { if defined (adrpost^.title) { add ("" + encode(adrpost^.title) + "")}; if defined (adrpost^.link) { add ("" + encode (adrpost^.link) + "")} else { //if the auto-generate-links pref is set, use a generated link if possible if adrblog^.prefs.flAutoGenerateLinks { if adrGetUrlCallback != nil { local (url, flincludelink = false); try {flincludelink = adrGetUrlCallback^ (adrpost, @url)}; if flincludelink { add ("" + url + "")}}}}}}; bundle { //add description, either from the cache, or by recalcing local (flrecalc = true); local (adritemcache = @adrcache^.items.[nameof (adrpost^)]); «if defined (adritemcache^) // ju «if timeModified (@adrpost^.text) <= adritemcache^.when «flrecalc = false local (fullitem = string (adrpost^.text)); // ju if flrecalc { local (itemtext = string (adrpost^.text)); bundle { //call the description filter callbacks, 4/11/02 by DW try { local (adrscript); for adrscript in @adrblog^.callbacks.rssFilterDescription { try { while typeof (adrscript^) == addresstype { adrscript = adrscript^}; itemtext = adrscript^ (itemtext, adrpost)}}}}; bundle { //process macros in the description, into itemtext, 4/7/02 by DW local (pt); new (tabletype, @pt); pt.macroStartCharacters = "<%"; pt.macroEndCharacters = "%>"; pt.processMacrosInHtmlTags = true; pt.tools = @radio.data.website.["#tools"]; try {itemtext = encode (html.processmacros (itemtext, adrpagetable:@pt))}; try { fullitem = encode (html.processmacros (fullitem, adrpagetable:@pt))}}; «itemtext = encode (radio.string.processMacros (string (adrpost^.text))) new (tabletype, adritemcache); adritemcache^.text = itemtext; adritemcache^.when = clock.now ()}; add ("" + adritemcache^.text + ""); add ("" + fullitem + "" ); add (""); «add (tidySuite.clean( string ( adrpost^.text) ) ) add ( string ( adrpost^.text ) ); add ("")}; «add ("" + adrpost^.when + "") // ju «add("" + date.netStandardString(adrpost^.when) + "") // ju local (s = html.getOneTagValue(xml.coercions.frontierValueToTaggedText(@adrpost^.when,0), "dateTime.iso8601")); regex.subst ( "([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9].*)", "\\1-\\2-\\3" + "-05:00", @s); add("" + s + "");; if defined (adrpost^.sourceName) and defined (adrpost^.sourceUrl) { add ("" + encode (adrpost^.sourceName) + "")}; if defined (adrpost^.enclosure) { with adrpost^.enclosure { if not defined (error) { add ("")}}}; «if flCategories «if defined (adrpost^.categories) «local (adr) «for adr in @adrpost^.categories «add ("" + encode (nameof (adr^)) + "") add (""); indentlevel--; lastitemdate = adrpost^.when; if ++ctitems >= adrblog^.prefs.maxOutputItemsPerChannel { break}}}}; add (""); indentlevel--; add (""); indentlevel--}; file.sureFilePath (f); file.writeTextFile (f, xmltext); scratchpad.rssWriterResult = xmltext; «dialog.alert( flCategories ) if ( flCategories == true ) { launch.application("c:\\radio\\tools\\fixrss.cmd");}; return (xmltext)}; «bundle //test code «local (tc = clock.ticks ()) «writeRssFile (user.radio.prefs.wwwfolder + "aaa.xml", "Test RSS File", "http://www.scripting.com/", "Oh the buzzing of the bees") «dialog.alert (clock.ticks () - tc)