/twitter.xql
xquery version "1.0";
(: -----------------------------------------------------------------------
A simple twitter client. This is the main script which is called from
controller.xql. It retrieves an atom feed from twitter and caches
it in the xmldb. The data is then passed to twitter-view.xql for
formatting and display.
-----------------------------------------------------------------------:)
declare namespace tc="http://exist-db.org/xquery/twitter-client";
declare namespace atom="http://www.w3.org/2005/Atom";
declare namespace html="http://www.w3.org/1999/xhtml";
import module namespace httpclient="http://exist-db.org/xquery/httpclient"
at "java:org.exist.xquery.modules.httpclient.HTTPClientModule";
import module namespace cache="http://exist-db.org/xquery/cache" at "java:org.exist.xquery.modules.cache.CacheModule";
(: To access more than just the tweets posted by a single user (e.g. its friends timeline),
you need to authenticate with a valid twitter account. Enter the username/password pair
below. :)
declare variable $tc:login := ( "user", "password" );
declare variable $tc:update-frequency := xs:dayTimeDuration("PT5M");
(: Create the HTTP basic authentication header if user credentials available :)
declare function tc:get-headers($credentials as xs:string*) {
if (empty($credentials)) then
()
else
let $auth := concat('Basic ', util:string-to-binary(concat($credentials[1], ':', $credentials[2])))
return
<headers>
<header name="Authorization" value="{$auth}"/>
</headers>
};
(: Send an HTTP request to twitter to retrieve the timeline in Atom format :)
declare function tc:get-timeline($credentials as xs:string*, $userId as xs:string, $view as xs:string) {
let $uri := xs:anyURI(
concat("http://twitter.com/statuses/", $view, "_timeline/", $userId, ".atom")
)
let $headers := tc:get-headers($credentials)
let $response := httpclient:get($uri, false(), $headers)
return
if ($response/@statusCode eq "200") then
$response/httpclient:body/*
else if ($response/httpclient:body//error) then
$response/httpclient:body//error/string()
else
concat("Twitter reported an error. Code: ", $response/@statusCode)
};
(: Retrieve the timeline and store it into the db cache :)
declare function tc:update-timeline($credentials as xs:string*, $userId as xs:string, $view as xs:string) {
let $tl := tc:get-timeline($credentials, $userId, $view)
let $cache := cache:cache("twitter")
let $cached := cache:put($cache, $userId, $tl)
return
$tl
};
(: Main function: returns the timeline in atom format. The data is cached within the database
and will be renewed every few minutes. :)
declare function tc:timeline($credentials as xs:string*, $userId as xs:string, $view as xs:string) {
let $feed := cache:get("twitter", $userId)
return
if (exists($feed) and
(xs:dateTime($feed/atom:updated) + $tc:update-frequency) > current-dateTime()) then
$feed
else
tc:update-timeline($credentials, $userId, $view)
};
(: This script will just retrieve the feed, then forward it to
twitter-view.xql, using a request attribute. The forwarding is done
through controller.xql :)
let $user := request:get-parameter("user", "existdb")
let $view := request:get-parameter("view", "user")
let $feed :=
tc:timeline(
if ($tc:login[1] eq 'user') then () else $tc:login,
$user, $view
)
return
request:set-attribute("twitter.feed", $feed)