m
xquery version "1.0"; (: This is the view part of the twitter client app. twitter.xql forwards the twitter timeline in the request attribute "twitter.feed". :) 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"; (: Parse the twitter message string. This function will recognize user names, links and tags. :) declare function tc:parse-content($content as xs:string) { let $filtered_text := $content let $filtered_text := replace($filtered_text,"(http://[A-z0-9/\.?=&\-_%]+)",'<a href="$1" class="url" target="new">$1</a>') let $filtered_text := replace($filtered_text,"@([A-z0-9/\.\-_]+)", '<a href="http://twitter.com/$1" class="username">@$1</a>') let $filtered_text := replace($filtered_text, "^([A-z0-9/\.\-_]+):", '<a href="http://twitter.com/$1" class="username">$1</a>:') let $filtered_text := replace($filtered_text,"&#([x0-9]+);","entity:$1") let $filtered_text := replace($filtered_text,"(&)","$1amp;") let $filtered_text := replace($filtered_text,"#([A-z0-9/\-_]+)", '<a href="http://search.twitter.com/search?q=%23$1">#$1</a>') let $filtered_text := replace($filtered_text,"\[\[entity:([x0-9]+)\]\]","&#$1;") let $filtered_text := concat("<span xmlns=""http://www.w3.org/1999/xhtml"" class='tw-body'>", $filtered_text, "</span>") return util:parse($filtered_text) }; (: Format an atom entry :) declare function tc:print-entry($entry as element(atom:entry), $mode as xs:string) { let $currentDate := adjust-date-to-timezone(current-date(), xs:dayTimeDuration("PT0H")) let $date := xs:dateTime($entry/atom:published) let $dateLine := if (xs:date($date) eq $currentDate) then xs:time($date) else $date return <li xmlns="http://www.w3.org/1999/xhtml"> { if ($mode eq 'html') then <span class="tw-thumb"> <img src="{$entry/atom:link[@rel = 'image']/@href}" height="48" width="48"/> </span> else () } <span class="tw-content"> <span class="tw-date">{$dateLine}</span> {tc:parse-content($entry/atom:content/node())} </span> </li> }; (: scan a set of HTML option elements and select the one whose value matches the $select argument :) declare function tc:set-options($select as xs:string, $options as element(html:option)+) { for $opt in $options return element { node-name($opt) } { if ($opt/@value eq $select) then attribute selected { "true" } else (), $opt/@*, $opt/node() } }; (: twitter.xql passes the timeline feed in request attribute "twitter.feed" :) let $feed := request:get-attribute("twitter.feed") let $user := request:get-parameter("user", ()) let $view := request:get-parameter("view", "user") let $mode := request:get-parameter("mode", "html") let $max := number(request:get-parameter("max", -1)) let $formattedFeed := if ($feed) then if ($feed instance of xs:string) then <li>Twitter reported an error: {$feed}</li> else let $entries := for $entry in $feed/atom:entry order by xs:dateTime($entry/atom:published) descending return $entry let $subset := if ($max lt 0) then $entries else subsequence($entries, 1, $max) for $entry in $subset return tc:print-entry($entry, $mode) else () return if ($mode eq 'html') then <html xmlns="http://www.w3.org/1999/xhtml"> <head> <style type="text/css"> body {{ margin: 0; font-family: "Bitstream Vera Sans", sans-serif; }} #container {{ margin: 20px auto; width: 620px; }} p {{ font-size: smaller; }} ul {{ list-style: none; padding: 0;}} .twitter li {{ position: relative; padding: 10px 0; }} .tw-thumb {{ height: 50px; display: block; position: absolute; left: 0; overflow: hidden; }} .tw-content {{ display: block; min-height: 50px; margin-left: 65px; line-height: 1.25em; }} .tw-body {{ display: block; }} .tw-date {{ display: block; font-size: small; color: #C0C0C0; padding-top: 4px; font-family: "Georgia", serif; }} .username {{ font-weight: bold; }} a {{ text-decoration: none; }} </style> </head> <body> <div id="container"> <form method="GET"> <label for="user">User: </label> <input type="text" name="user" size="15" value="{if ($user) then $user else 'existdb'}"/> <select name="view"> { tc:set-options($view, ( <option value="user">User Timeline</option>, <option value="friends">Friends Timeline</option> )) } </select> <input type="submit" value="Show"/> </form> <p>To view the friends timeline, edit twitter.xql and set variable $tc:login to a valid twitter user/password.</p> <ul class="twitter"> { $formattedFeed } </ul> </div> <p class="view-source">View source: <a href="twitter.xql/source">twitter.xql</a>, <a href="twitter-view.xql/source">twitter-view.xql</a></p> </body> </html> else let $null := util:declare-option("exist:serialize", "method=text media-type=application/json") let $asString := replace(util:serialize($formattedFeed, "indent=no"), "'", "\\'") let $body := concat('<ul class="twitter">', $asString, '</ul>') return concat("twitterCallback('", $body, "')")