SwikiRssFeed
These are my suggestion for someone's wish "It would be a real time saver if Swiki had the ability to create a RSS feed."
Tip #1: Creating a new swiki providing RSS feed
Create a new swiki named, for example, "rssdoc"
Using SwikiBrowser, add following templates for new "rssdoc" swiki:
addresses(book)-rss
actions(book)-description
actions(book)-url
actions(page)-description
actions(page)-iso8601Date
actions(page)-timeStamp
Create a new swiki inheriting rssdoc (which in turn inherits from 'refs' swiki). Or you can modify an existing swiki's parent as 'rssdoc' using SwikiBrowser
Now you can address like "http://yourserver/yourswiki/rss" to get RSS feed of your 'Recent Changes'
addresses(book)-rss
| formatter testDate sortedPages item test selectedPages |
response at: 'contentType' put: 'text/xml'.
formatter _ BookTemplateFormatter swikiFormatter.
testDate _ Date today subtractDays: 8.
sortedPages _ (book pages asSortedCollection: [:x :y | (x date = y date) ifTrue: [x time > y time] ifFalse: [x date > y date]]) asOrderedCollection.
item _ 1.
[(test _ sortedPages at: item ifAbsent: [nil])
ifNil: [false]
ifNotNil: [test date > testDate]] whileTrue: [item _ item + 1].
item _ item - 1.
(item < 5)
ifTrue: [(sortedPages size < 5)
ifTrue: [selectedPages _ sortedPages]
ifFalse: [selectedPages _ sortedPages copyFrom: 1 to: 5]]
ifFalse: [(item < 30)
ifTrue: [selectedPages _ sortedPages copyFrom: 1 to: item]
ifFalse: [selectedPages _ sortedPages copyFrom: 1 to: 30]].
TextFormatter crToCrlf:
(
String streamContents: [ :strm |
" RSS std header "
strm nextPutAll:
'
'.
" RSS site info "
strm nextPutAll: (
formatter
format:
'
'
request: request
response: response
shelf: shelf
book: book
).
" ========================================= "
" RSS pages info "
selectedPages do: [:page |
strm nextPutAll: (
formatter format:
'-
#
'
request: request
response: response
shelf: shelf
book: book
page: page
)
].
" ========================================= "
" RSS std trailer "
strm nextPutAll:
'
'.
]
)
actions(book)-description
(book settingsAt: 'description')
actions(book)-url
'http://', (request raw header at: 'host'), (request referenceShelf: shelf book: book)
actions(page)-description
| contents |
" apply asString handle dictionary type text "
contents _ (page showFormat: page text asString request: request response: response shelf: shelf book: book) findTokens: (' <>&;',String crlf) keep: '<>&;'.
String streamContents: [ :strm |
| i cnt seekLtEnd seekAmpEnd |
i _ 1.
cnt _ 0.
seekLtEnd _ false.
seekAmpEnd _ false.
[ (i <= contents size) and: [ cnt < 50 ] ] whileTrue: [
| tok |
tok _ contents at: i.
('<' = tok) ifTrue: [
seekLtEnd _ true.
] ifFalse: [
('&' = tok) ifTrue: [
seekAmpEnd _ true.
] ifFalse: [
seekLtEnd ifTrue: [
('>' = tok) ifTrue: [
seekLtEnd _ false.
]
] ifFalse: [
seekAmpEnd ifTrue: [
(';' = tok) ifTrue: [
seekAmpEnd _ false.
]
] ifFalse: [
strm nextPutAll: tok;
nextPut: $ .
cnt _ cnt + 1
]
]
]
].
i _ i + 1.
]
]
actions(page)-iso8601Date
" dc:date format (iso8601) example: 2003-10-15T10:03:33+09:00 "
((page date) printFormat: #(3 2 1 $- 1 1 2)), 'T', ((page time) print24), '+00:00'
actions(page)-timeStamp
(TimeStamp date: (page date) time: (page time)) asSeconds asString
Tip #2: Using a perl CGI script converting swiki "Recent changes" page into RSS format
Get swiki-to-rss.pl and rename it to swiki-to-rss.cgi if needed. Install it as a CGI script for your apache or other legacy web-server.
To access RSS summary of any swiki you want, access this CGI script like this:
http://yourserver/cgi-bin/swiki-to-rss.cgi?proto=&host=&port=&swiki=&lang=&enc=&tzo=[&cronly=1]
For Example:
http://yourserver/cgi-bin/swiki-to-rss.cgi?host=minnow.cc.gatech.edu&swiki=squeak
http://yourserver/cgi-bin/swiki-to-rss.cgi?host=minnow.cc.gatech.edu&swiki=swiki
swiki-to-rss.pl looks like:
#!/usr/bin/env perl
use CGI qw/:standard/;
use Net::HTTP;
use Date::Format;
use Date::Parse;
#use 5.8.0;
#use strict;
use Encode;
use Encode::Alias;
$debug = 0;
$query_string = $ENV{QUERY_STRING};
$script_descr = "Swiki-to-rss.cgi v0.1";
$agent_string = "Swiki-to-RSS/0.1";
$ttl = 60; # refresh interval in unit of minutes
sub usage_and_exit {
local($msg) = shift;
print header( -type=>'text/plain' );
print $msg,"\n";
print "Usage: swiki-to-rss.cgi?proto=&host=&port=&swiki=&lang=&enc=&tzo=\n";
print "tz-offset must be in unit of hours (plus or minus)\n";
exit 0;
}
sub tzo_to_tz {
local $o = shift;
sprintf("%s%02d00",($o>0)?"-":"+",abs($o));
}
sub tzo_to_8601tz {
local $o = shift;
sprintf("%s%02d:00",($o>0)?"-":"+",abs($o));
}
sub time_to_rfc822 {
local $t = shift;
time2str("%a, %d %b %y %H:%M:%S %Z",$t,"GMT");
}
sub time_to_iso8601 {
local $t = shift;
local $z = shift;
time2str("%Y-%m-%dT%H:%M:%S",$t,&tzo_to_tz($z)).&tzo_to_8601tz($z);
}
sub escape_line {
local $l = shift;
local %escape = ('<'=>'<', '>'=>'>', '&'=>'&', '"'=>'"');
local $escape_re = join '|' => keys %escape;
$l =~ s/($escape_re)/$escape{$1}/g;
$l;
}
$host = param('host');
$swiki = param('swiki');
print STDERR "host=$host, swiki=$swiki" if $debug;
(!defined($host) || !defined($swiki))
& &usage_and_exit("\`host' and \`swiki' should be specified");
$proto = param(proto) || "http";
$port = param('port');
$lang = param('lang') || "en";
$enc = param('enc');
$tzo = param('tzo') || "5";
$port = ":${port}" if defined($port);
$tz = &tzo_to_tz($tzo);
$remote = $ENV{HTTP_X_FORWARDED_FOR};
if ( !defined($remote)
|| $remote =~ m/^127\./
|| $remote =~ m/^10\./
|| $remote =~ m/^192\.168\./
|| $remote =~ m/^169\.254\./
) {
$remote = $ENV{REMOTE_ADDR};
}
my $s = Net::HTTP->new(Host => "${host}${port}") ||
&usage_and_exit("Cannot connect [${host}${port}]");
$s->write_request(GET => "/${swiki}/recent",
'User-Agent' => ${agent_string},
'X-forwarded-for' => $remote );
my($code, $mess, %h) = $s->read_response_headers;
if (200 != $code) {
&usage_and_exit("${code}: ${mess}: Cannot fetch [${proto}://${host}${port}/${swiki}/recent]");
}
$out = qq`
`;
$contents = "";
while (1) {
my $buf;
my $n = $s->read_entity_body($buf, 1024);
#die "read failed: $!" unless defined $n;
last unless $n;
$contents .= $buf;
}
#print STDERR $contents if $debug;
@Contents = split(/[\r\n]+/,$contents);
#print STDERR join('##',@Contents) if $debug;
foreach $n (@Contents) {
# print STDERR "\n" if ($body_open & $debug);
if (!$body_open) {
$body_open = ($n =~ m`^(.*)`) {
$title = $0;
$ctitle = "$title " if defined($title);
$http_hdrs = join("^",%h);
$http_hkeys = join("^",keys(%h));
$http_hvals = join("^",values(%h));
$ctype = $h{"Content-type"};
if ($ctype =~ m/;\s*charset=\"?([^\"]+)\"?/) {
$enc = $1;
}
$out .= qq`
${ctitle}
${proto}://${host}${port}/${swiki}
${title}
${lang}
${script_descr}
${ttl}
`;
}
} else {
if ($n =~ m`([0-9]+)\s(\S+)\s([0-9]+) `) {
$dts = "$1 $2 $3";
}
if ($n =~ m`(.*) \s+at\s+(.*\s+[ap]m)(\s+by\s+(\S+))?\s$`) {
$iswiki=$1;
$item=$2;
$ititle=$3;
$timestring = $4;
$author = $6;
$authorfield = defined($author) ? "${author} " : "";
# for ${gt}${toff}
$tmsrc = "${dts} ${timestring} ${tz}";
$tm = str2time($tmsrc,$tz);
$tm8601 = &time_to_iso8601($tm,$tzo);
$tm822 = &time_to_rfc822($tm);
$ilink = "${proto}://${host}${port}/${iswiki}/${item}";
# Feedreader hack. (which do not considers guid to check updated item)
$ilink .= "#${tm}" if ($ENV{'HTTP_USER_AGENT'} =~ m`^Feedreader`);
$guid = "${proto}://${host}${port}/${iswiki}/${item}#${tm}";
$out .= qq`-
${ititle}
${ilink}
${swiki}
${authorfield}
${guid}
${tm822}
${tm8601}
`;
}
}
}
$out .= qq`
`;
if (defined($enc)) {
Encode::from_to($out, $enc, "utf-8", 0);
}
print header( -type=>'text/xml',
-charset=>'utf-8',
-pragma=>'no-cache',
-cache_control=>'no-cache',
-expires=>'0',
# -content_length=>length($out)
);
$\ = "\r\n";
print $out;
0;
My wish is that these will be helpful for someone. :-) –shr
Link to this Page
Swiki Wishlist last edited on 5 November 2006 at 10:01 pm by penguin.cc.gatech.edu