hook up a cloud

running your own weblog tracker and want blo.gs to let you know when we know about updated blogs? the cloud interface is for you, then.

First contact us with the IP address(es) that you will use to attach to the cloud, we need to allow access to the cloud before you can connect. simply connect to port 29999 on ping.blo.gs, and you will be receiving a streaming version of the old changes.xml files.

the output of the service looks like this:

<?xml version="1.0" encoding="utf-8"?>
<weblogUpdates version="1" time="20041127T22:51:58Z">
<weblog name="blog one"
    url="http://example.com/blogone/"
    rss="http://example.com/blogone/index.rss"
    service="ping" ts="20041127T22:51:59Z"
/>
<weblog name="blog two"
    url="http://example.com/blogtwo/"
    service="ping" ts="20041127T22:52:06Z"
/>
<weblog name="blog three"
    url="http://example.com/blogthree/"
    service="blogger.com"
    polled="true" ts="20041127T22:47:38Z" />
</weblogUpdates>

what follows is an example of using this service using a command-line php program. the program should be run like:

listener ping.blo.gs 29999
#!/usr/bin/php5
<?php # vim: ft=php

$host $argv[1];
$port $argv[2];

if (!
$host || !$port)
    die(
"usage: $argv[0] hostname port\n");

$s stream_socket_client(
    
"tcp://$host:$port",
    
$errno$errstr10
);
#stream_filter_append($s, 'zlib.inflate');
if (!$s)
    die(
"$argv[0]: failed to connect ($errno): $errstr\n");

$parser xml_parser_create("utf-8");
xml_parser_set_option(
    
$parser,
    
XML_OPTION_TARGET_ENCODING,
    
'UTF-8'
);
xml_set_element_handler(
    
$parser,
    
"start_element",
    
"end_element"
);

while (!
feof($s)) {
    
$buff fread($s2048);
    
$success xml_parse($parser$bufffalse);

    if (!
$success) {
        
$err xml_get_error_code($parser);
        
$line xml_get_current_line_number($parser);
        
$col xml_get_current_column_number($parser);
        die(
            
"xml parsing failed on line $line, column $col: " .
            
xml_error_string($err) .
            
" ($err)\n" gzinflate($buff) . "\n"
        
);
    }
}

function 
start_element($parser$tag$attrs) {
    global 
$service;
    if (
$tag == 'WEBLOGUPDATES') {
        
$ts decode_datetime($attrs['TIME']);
        if (!
$ts) die("unable to parse: $attrs[TIME]");
        
$local date('r'time());
        
$remote date('r'$ts);
        echo 
"local time: $local, remote time: $remote\n";
    } elseif (
$tag == 'WEBLOG') {
        
$name $attrs['NAME'];
        
$url $attrs['URL'];
        
$rss    $attrs['RSS'] ? $attrs['RSS'] : '';
        
$service $attrs['SERVICE'] ? $attrs['SERVICE'] : '';
        
$when decode_datetime($attrs['TS']);
        
$date date('r'$when);

        echo 
"$service $url $name at $date\n";
    }
}

function 
end_element() {
    
# we don't care
}

function 
decode_datetime($ts) {
    if ( 
preg_match(
        
'/^(\d{4})(\d{2})(\d{2})T(\d{2}):(\d{2}):(\d{2})Z?$/',
        
$ts$m)
    ) {
        if (
$m[1] < 1970)
            return 
false;
        return 
gmmktime($m[4],$m[5],$m[6],$m[2],$m[3],$m[1]);
    }
    return 
false;
}

faq

what's the deal with the timestamp? can't i just assume the weblog was updated at the current time?

no. the timestamp makes it possible for a skyful of clouds to pass along updates without creating loops. note in the example how one of the updates has service="blogger.com" polled="true", which means it came into the system via a poll of the list of updated blogs that blogger publishes.

i'm writing an rss/atom news client, and want to use the blo.gs updates to trigger reloading of feeds. is that okay?

absolutely not. this service is intended for use in providing services that can benefit from real-time updates about all blogs — users that need information only about a subset of this data will need to obtain it elsewhere.

any abuse or inappropriate usage of this service may result in this service being discontinued or your access to it being terminated.