ljr/local/htdocs/stats/latest-rss.bml

111 lines
4.2 KiB
Plaintext
Executable File

<?_code
{
use strict;
BML::set_content_type("text/xml");
my $recent = LJ::MemCache::get("blob:ljcom_latestposts2") || [];
my $ret = "<?xml version='1.0'?>\n";
$ret .= <<"EOT";
<!--You can poll this feed as often as you like, but please don't spider the links.
Mail dev\@livejournal.com if you have any questions/interesting research ideas.-->
EOT
$ret .= "<rdf:RDF ".
"xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' ".
"xmlns:dc='http://purl.org/dc/elements/1.1/' ".
"xmlns:lj='http://livejournal.org/rss/lj/1.0/' ".
"xmlns='http://purl.org/rss/1.0/'>\n";
$ret .= "<channel rdf:about='$LJ::SITEROOT/stats/latest-rss.bml'><title>Latest $LJ::SITENAME Posts</title><link>$LJ::SITEROOT/stats/latest.bml</link><description>Latest public posts at $LJ::SITENAME.</description>\n";
# setup for security logging
my %securities = (
public => 0,
private => 0,
friends => 0,
custom => 0,
);
# retrieve posts.
my @postids;
foreach my $p (@$recent) {
$securities{$p->{security}}++;
next unless $p->{security} eq 'public';
$p->{ditemid} = $p->{itemid}*256 + $p->{anum};
$p->{urn} = "urn:$LJ::DOMAIN:entry:$p->{journalu}{user}:$p->{ditemid}";
push @postids, [ $p->{clusterid}, $p->{journalu}{userid}, $p->{itemid} ];
}
my $rawposts = LJ::get_posts_raw({memcache_only=>1}, @postids);
my $rdftoc = "<items><rdf:Seq>\n";
my $rdfitems = "";
foreach my $p (@$recent) {
next unless $p->{security} eq 'public';
my $uj = $p->{'journalu'};
my $up = $p->{'journalp'};
my $id = "$uj->{userid}:$p->{itemid}";
my $props = $rawposts->{prop}{$id};
# we shouldn't expect every post to be in the memcache.
next unless $rawposts->{text}{$id};
# skipping unknown8bit users sucks, but we can't load users here.
next if $props->{unknown8bit};
$rdftoc .= " <rdf:li resource='$p->{urn}' />\n";
my $url = LJ::journal_base($uj) . "/$p->{ditemid}.html";
my ($subject, $body) = @{$rawposts->{text}{$id}};
$rdfitems .= "<item rdf:about='$p->{urn}'>\n";
# first, the required RDF elements.
# we use title to represent all the metadata in one string,
# then dublin core for the data in pieces.
$rdfitems .= "<title>$up->{'user'}";
$rdfitems .= " (in $uj->{'user'})" if $uj->{userid} != $up->{userid};
$rdfitems .= ": " . LJ::exml($subject) if $subject;
$rdfitems .= "</title>\n";
$rdfitems .= "<description>" . LJ::exml($body) . "</description>\n";
$rdfitems .= "<category>$_</category>\n" foreach map { LJ::exml($_) } @{$p->{tags} || []};
$rdfitems .= "<link>$url</link>\n";
# use dc for the rest.
$rdfitems .= "<dc:title>" . LJ::exml($subject) . "</dc:title>\n" if $subject;
$rdfitems .= "<dc:creator>" . LJ::exml($up->{name}) . " ($up->{user})</dc:creator>\n";
$rdfitems .= "<dc:publisher>" . LJ::exml($uj->{user}) . "</dc:publisher>\n"
if $uj->{userid} != $up->{userid};
$rdfitems .= "<dc:date>" . LJ::time_to_w3c($p->{timepost}) . "Z</dc:date>\n";
# and lj for the lj-specific data.
my $mood = $props->{current_mood};
$mood ||= LJ::mood_name($props->{current_moodid}) if $props->{current_moodid};
my $moodid = " id='$props->{current_moodid}'" if $props->{current_moodid};
$rdfitems .= "<lj:mood$moodid>" . LJ::exml($mood) . "</lj:mood>\n"
if $mood or $moodid;
$rdfitems .= "<lj:music>" . LJ::exml($props->{current_music}) . "</lj:music>\n"
if $props->{current_music};
$rdfitems .= "<lj:pickeyword>" . LJ::exml($props->{picture_keyword}) . "</lj:pickeyword>\n"
if $props->{picture_keyword};
$rdfitems .= "</item>\n";
}
$rdftoc .= "</rdf:Seq></items></channel>\n";
$ret .= $rdftoc . $rdfitems;
$ret .= "</rdf:RDF>\n";
$ret .= <<"EOT";
<!-- Security breakdown:
public: $securities{public} (shown above)
private: $securities{private}
friends: $securities{friends}
custom: $securities{custom} -->
EOT
return BML::noparse($ret);
}
_code?>